Compare commits

...

243 Commits

Author SHA1 Message Date
games647
6fd1e5e79c Fix TCPShield compat by using raw address for sessions
TCPShield overwrites the IP address during connection. ProtocolLib
doesn't notice this change, because it uses the end-to-end connection
which is the proxy IP. This causes getAddress calls during Spigot play
state and ProtocolLib auth state not match and then have conflicting
session ids.

A solution is also to hold onto the temporary player object. However
since we don't get a notification for a disconnect, holding it will
prevent to get GCed until the timeout occurs (1 minute).

Fixes #595
2021-08-14 21:01:56 +02:00
games647
213bacfab9 Add extra session logging 2021-08-14 17:05:27 +02:00
games647
232e9ac137 Use the address field for verify task 2021-08-14 17:05:18 +02:00
games647
f8fe3d7d71 Do not silence exceptions for Floodgate 2021-08-12 20:39:14 +02:00
games647
4d4ecf3da7 Merge pull request #583 from games647/dependabot/maven/org.slf4j-slf4j-jdk14-1.7.32
Bump slf4j-jdk14 from 1.7.31 to 1.7.32
2021-07-26 10:06:59 +02:00
dependabot[bot]
f80059987b Bump slf4j-jdk14 from 1.7.31 to 1.7.32
Bumps [slf4j-jdk14](https://github.com/qos-ch/slf4j) from 1.7.31 to 1.7.32.
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/commits)

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-26 07:02:17 +00:00
games647
6e0272d92c Fix receiving login packet twice with ProtocolLib
Fixes #578
Commit that introduces the bug:
1f4757669c
2021-07-16 14:24:17 +02:00
games647
758ccb9bf2 Clean up 2021-07-14 16:33:31 +02:00
games647
0515ac193d Extract protocollib method detection 2021-07-14 16:33:18 +02:00
games647
864e551a88 Disable verbose verification output
NameChange fix is resolved
2021-07-14 16:32:32 +02:00
games647
0a24d36ef8 [ci skip] Rephrase development build section
Fixes #576
2021-07-12 17:25:52 +02:00
games647
8a535e1ad9 [ci skip] Merge pull request #574 from MAX-XiaoKui/patch-1
Update plugin SodionAuth's link. Its URL has changed.
2021-07-10 17:18:08 +02:00
MAX_小葵
ae66f1ab35 Update plugin SodionAuth's link 2021-07-10 22:04:54 +08:00
games647
ed725d991e [ci skip] Show user clickable links 2021-07-06 11:25:52 +02:00
games647
e45d4b3482 [ci skip] Require what happened form 2021-07-06 11:20:36 +02:00
games647
b5b5faaefb [ci skip] Add feedback message to forms 2021-06-30 17:23:54 +02:00
games647
51a28ae93f [CI-SKIP] Fix issue template syntax 2021-06-30 17:04:16 +02:00
games647
d2fcdade0b [CI-SKIP] Try out issue forms 2021-06-30 17:02:19 +02:00
games647
cde045d6fd Only build for main branches to fix duplicate actions with dependabot 2021-06-29 12:55:37 +02:00
games647
ccdc455ce9 Clarify naming and structure 2021-06-22 14:07:47 +02:00
games647
4e1f5e9401 Add icons to issue templates 2021-06-22 13:25:57 +02:00
games647
2e64b52261 Migrate questions to discussions 2021-06-22 13:25:41 +02:00
games647
1f4757669c Allow packet modifications by other plugins
If we disable filters, other plugins are advised to only monitor
packets. Potential modifications can be allowed by enabling the filtering again, but adding our meta data to prevent duplicate
processing.
2021-06-22 11:15:21 +02:00
games647
496817afca Increase the rate limit for bigger servers
Related #406
2021-06-21 18:00:45 +02:00
games647
daf6f06a00 Name anti-bot feature explicitly for own rate limiting 2021-06-21 17:33:38 +02:00
games647
4be0e1333d [CI-SKIP] Add issue template descriptions 2021-06-21 17:08:20 +02:00
games647
58cee1e26e Exclude more transitive dependencies
This could reduce the number of required
downloads as well as to prevent download
from legacy HTTP non secure (not HTTPS)
sources.
2021-06-21 17:08:20 +02:00
games647
9f89756820 Disable plugin if dependencies not available
Related #554
2021-06-21 17:08:20 +02:00
games647
d1daec436c Merge pull request #559 from Smart123s/fg2-ln-autoreg
Add 'linked' option to 'autoRegisterFloodgate'
2021-06-21 16:31:25 +02:00
Smart123s
2626c21bc8 Add 'linked' option to 'autoRegisterFloodgate'
This makes sense with Floodgate 2.0's Global Link API
2021-06-21 15:15:18 +02:00
games647
5607a19312 Merge pull request #560 from Smart123s/fg-player-to-account
Update messages
2021-06-21 14:30:46 +02:00
games647
1f950397a4 Merge pull request #561 from games647/dependabot/maven/org.slf4j-slf4j-jdk14-1.7.31
Bump slf4j-jdk14 from 1.7.30 to 1.7.31
2021-06-21 12:07:45 +02:00
dependabot[bot]
08e26dd60f Bump slf4j-jdk14 from 1.7.30 to 1.7.31
Bumps [slf4j-jdk14](https://github.com/qos-ch/slf4j) from 1.7.30 to 1.7.31.
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/commits)

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-jdk14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 07:03:13 +00:00
Smart123s
2ffe7e0daf Replace word 'Player' with 'Account' in messages.
Technically speaking, one player can own both the Java and the Bedrock
account with the same name, so it's more appropriate to say account
instead of player.
2021-06-20 17:44:46 +02:00
Smart123s
33261b9ea6 Floodgate 2.0 is no longer in a seperate branch 2021-06-20 17:37:18 +02:00
games647
5442f773ae Merge pull request #558 from Smart123s/fg-sharedtask
Add Floodgate config options for BungeeCord
2021-06-20 14:03:45 +02:00
Smart123s
fd3da28bec Use Override for non core code in FloodgateAuthTas 2021-06-20 13:35:31 +02:00
Smart123s
9350f52916 Create a seperate function for isNameCheckRequired 2021-06-20 13:23:51 +02:00
Smart123s
7c2bb9c9a4 Don't spam log when with unregistered floodgate 2021-06-20 13:05:04 +02:00
Smart123s
0b307a95a3 Add further documentation to config.yml
Floodgate options are no longer Bukkit only
autoRegister/LoginFloodgate needs normal (Java) autoRegister/Login
to be set to ture
2021-06-20 11:26:15 +02:00
Smart123s
ed627ce438 Add autoLogin and register for Floodgate Bungee 2021-06-20 11:26:14 +02:00
Smart123s
af83604c94 Remove existing Floodgate integration from Bungee 2021-06-20 11:26:13 +02:00
Smart123s
8f43cc0978 Partially move FloodgateAuthTask to Core
The moved code can be used in a BungeeCord implementation
2021-06-20 11:26:13 +02:00
games647
578028719f Merge pull request #556 from Smart123s/patch-5
FloodgateNameConflict no longer needs autoLogin
2021-06-19 10:43:09 +02:00
Péter Tombor
b87b59be12 FloodgateNameConflict no longer needs autoLogin
The removed line is not valid after 1f3cd5fa5b
2021-06-18 23:25:46 +02:00
games647
f17f9d983a Merge pull request #551 from games647/codeql
CodeQL Test
2021-06-17 14:52:09 +02:00
games647
6cbd64b06d Cache autobuild process 2021-06-17 14:23:18 +02:00
games647
8d588ff7db Document codeql workflow file 2021-06-17 14:23:17 +02:00
games647
92e05c460f Create CodeQL scanning workflow 2021-06-17 14:23:17 +02:00
games647
b9011b6141 Add support for 1.17
Fixes #552
2021-06-15 20:46:25 +02:00
games647
7fdbedb8c1 Merge pull request #533 from Smart123s/fg-bk-nonconfict
Add 'no-conflict' option to some Floodgate config entries
2021-06-15 11:30:06 +02:00
games647
baede33abc Make Bedrock check nullsafe
If the UUID was not set by FloodGate or any other plugin, it's null
by in BungeeCord

Fixes #548
2021-06-15 10:31:53 +02:00
Smart123s
2e83eaaa81 Remove unused import 2021-06-14 19:42:56 +02:00
Smart123s
fb8780d006 Prevent duplicate name check API call
Previously: If allowFloodgateNameConflict = false or linked and either autoLoginFloodgate or
autoRegisterFloodgate is set to no-conflict and a player with a non-conflicting name
connects then there will be a double check.
2021-06-14 19:16:40 +02:00
Smart123s
4c0797d5ea No longer treat linked Floodgate players as conflicting names
Since linked players inherit the name of the Java player, it'll always conflict a Java player 's name
2021-06-14 19:16:04 +02:00
Smart123s
235d7f8d80 Add 'no-conflict' as an option to config.yml value checking 2021-06-14 19:16:04 +02:00
Smart123s
dbf10f4767 Remove unnecessary whitespaces 2021-06-14 19:16:02 +02:00
Smart123s
fed1e91b28 Document 'no-conflict' in config.yml 2021-06-14 19:09:54 +02:00
Smart123s
dc8dd13d5b Expand possible values in config.yml 2021-06-14 19:09:54 +02:00
Smart123s
165e5fe856 Add 'no-conflict' option to some Floodgate config entries 2021-06-14 19:09:43 +02:00
games647
01c9b55d80 Merge pull request #545 from games647/dependabot/github_actions/actions/setup-java-2.1.0
Bump actions/setup-java from 1.4.3 to 2.1.0
2021-06-14 10:37:40 +02:00
games647
4cf660559e Merge pull request #532 from Smart123s/fg-bk-ncshare
Share Floodgate name conflict check between Protocol Plugins
2021-06-14 10:37:11 +02:00
games647
11c38bdb15 Set required distribution name 2021-06-14 10:35:10 +02:00
dependabot[bot]
0d9e30be8d Bump actions/setup-java from 1.4.3 to 2.1.0
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 1.4.3 to 2.1.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v1.4.3...v2.1.0)

---
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>
2021-06-13 18:08:09 +00:00
games647
edb4179ba6 Ignore provided guava dependency 2021-06-13 20:06:44 +02:00
games647
e0ddfec921 Drop not needed specific time and number limits 2021-06-13 20:06:44 +02:00
games647
b2fef5e6d6 Update GitHub actions with dependabot too 2021-06-13 20:06:44 +02:00
games647
02db1041e2 Be explicit about the license name 2021-06-13 20:06:43 +02:00
games647
04428fe146 Merge pull request #543 from Smart123s/fix-warnings
Get rid of several warning messages
2021-06-13 19:42:20 +02:00
Smart123s
9656aadb35 Remove unused imports 2021-06-13 16:50:36 +02:00
Smart123s
c0d21fdca2 Remove 'handlerFound' from ConnectListener 2021-06-13 16:48:01 +02:00
Smart123s
c1cf80fe28 Remove 'initialHandlerClazzFound' from ConnectL... 2021-06-13 16:44:57 +02:00
Smart123s
9acab1e453 Don't store 'floodgateVersion' in ConnectListener 2021-06-13 16:43:38 +02:00
Smart123s
d51335c6de Don't store 'ultraAuthPlugin' 2021-06-13 16:36:04 +02:00
Smart123s
2fdcc34575 Don't store 'plugin' in BukkitScheduler 2021-06-13 16:33:47 +02:00
Smart123s
66a51a8e13 Remove unused 'serverId' from BukkitLoginSession 2021-06-13 16:31:39 +02:00
Smart123s
411148b560 No longer reference 'Floodgate' in JoinManagement
Referencing 'FloodgatePlayer' in JoinManagement.java and it's subclasses
has cause ProtocolLib to fail to register an event when Floodgate was not
installed.
2021-06-13 14:24:14 +02:00
games647
d1109ac75e Merge pull request #542 from Smart123s/patch-4
Add license header to FloodgateAuthTask.java
2021-06-12 20:08:30 +02:00
Smart123s
af0ef2aed9 Stop ProtocolSupport from crying
If I ever tried to either cast or use FloodgatePlayer as a return type
when Floodgate was not installed in the server, I got this error:

[19:37:46 ERROR]: [FastLogin] Plugin FastLogin v1.11-SNAPSHOT-744264d has failed to
register events for class
com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener
because org/geysermc/floodgate/api/player/FloodgatePlayer does not exist.

ProtocolLib doen't have this problem.
2021-06-12 19:57:32 +02:00
Smart123s
ee2b3a37f8 Move Floodgate name conflict check to Core 2021-06-12 19:57:31 +02:00
Smart123s
0e8ad6e318 Add license header to FloodgateHook.java 2021-06-12 19:56:36 +02:00
Péter Tombor
bc8fffe063 Add license header to FloodgateAuthTask.java 2021-06-12 19:51:15 +02:00
Smart123s
757d0ef991 Fix & Move allowFloodgateNameConflict=linked 2021-06-05 18:43:23 +02:00
Smart123s
2d5a53a2f9 Kick player if Floodgate name conflict checking fails
Rebased on  Sat May 22 13:48:29 2021 +0200
Fixed typos in strings
2021-06-05 18:43:23 +02:00
Smart123s
9a6112ebd4 Made ProtocolSupport check for Floodgate name conflicts
Rebased on Sat May 22 11:42:34 2021 +0200
Initialize FloodgateHook in constructor
This way, it won't have to be initialized whenever a player joins
2021-06-05 18:42:30 +02:00
Smart123s
1f3cd5fa5b Share Floodgate name conflict check between Protocol Plugins
Added a shared class for Floodgate name conflict checking that can be used by both ProtocolLib and ProtocolSupport

Rebased on Sat May 22 11:42:08 2021 +0200
Added access modifier to "FastLoginBukkit plugin;" in FloodgateHook.java

Rebased on Sat May 22 11:42:08 2021 +0200
Initialize FloogateHook in ProtocolLib's class
2021-06-05 18:40:15 +02:00
games647
e8bb9fd30a Merge pull request #534 from Smart123s/patch-3
Warn in config: linked players conflict their Java name
2021-05-23 13:53:20 +02:00
Péter Tombor
0d5413d402 Warn in config: linked players conflict their Java name 2021-05-22 21:17:11 +02:00
games647
119b9cb000 Merge pull request #494 from Smart123s/main
Floodgate support for Bukkit
2021-05-16 20:50:53 +02:00
Smart123s
d44ab4e634 Warn when unsupported plugins are detected
Floodgate 1.0 does not work with the current Bukkit implementation.
ProtocolLib and Floodgate don' play along nicely when used with FastLogin
Related issue: #493
2021-05-16 17:54:50 +02:00
Smart123s
b2b61539e1 Revert "Move Floodgate conflict chechking to core"
This reverts commit b0ef1a59ac.
2021-05-16 17:54:50 +02:00
Smart123s
b9dd921885 Change plugin.yml to softepend on Floodgate 2.0
Rebased to remove Bungee related changes
2021-05-16 17:53:22 +02:00
games647
6b20b71403 Merge pull request #530 from Smart123s/patch-2
Change dependency Floodgate Bungee to API
2021-05-16 16:08:14 +02:00
Péter Tombor
40b9405c1d Change dependency Floodgate Bungee to API
Same functionality, less code to be downloaded.
2021-05-15 11:58:43 +02:00
games647
1385f0c730 Merge pull request #528 from Smart123s/patch-1
Actually assign the queried version to a variable
2021-05-13 17:21:47 +02:00
Péter Tombor
a8c1570dd3 Actually assign the queried version to a variable
The Floodgate version was queried, but it's return value wasn't actually assigned to a variable.

Edited this from mobile GitHub website. I have no code check here.
2021-05-13 15:12:13 +02:00
games647
3d65a33e0c Merge pull request #527 from TechnicallyCoded/feature/floodgate-v2.0
Implement floodgate api version 2.0
2021-05-13 15:07:21 +02:00
TechnicallyCoded
2700b3ee0e Implement floodgate api version 2.0 2021-05-12 11:49:15 +02:00
Smart123s
5858bfb443 Add Floodgate name conflict check to ProtocolSupport 2021-05-09 11:10:10 +02:00
Smart123s
b0ef1a59ac Move Floodgate conflict chechking to core
The FloodgateApi is the same for Bukkit and Bungee, so the Floodgate
related code could be used in a future Bungee implementation too.

Currently, Bungee will report Floodgate disabled to core, so the
upstream Floodgate implementation will be used there.
If enough code will be moved to core, I might consider enabling these
features to BungeeCord too.
2021-05-09 11:01:36 +02:00
Smart123s
25254b2393 Add vscode to .gitignore 2021-05-09 09:09:52 +02:00
Smart123s
08b864220d Merge branch 'main' of https://github.com/games647/FastLogin 2021-05-09 09:06:59 +02:00
games647
dbe9ac2903 Merge pull request #525 from Smart123s/fg2-bc
Fix Floodgate 2.0 on BungeeCord
2021-05-08 19:18:24 +02:00
Smart123s
1b7b2ff2b5 Add support for Floodgate 2.0 2021-05-08 16:26:58 +02:00
Smart123s
d01c368cdb Fix identation in bukkit/pom.xml 2021-05-08 14:46:00 +02:00
Smart123s
75750f8417 Apostrophes are no longer necessary in config.yml 2021-05-08 14:20:56 +02:00
Smart123s
85a1abfaac Describe how UUIDs work for 'allowFloodgateNameConflict' in config.yml 2021-05-08 13:38:38 +02:00
Smart123s
5a263956fe Fixed Java auto login/register 2021-05-06 11:56:24 +02:00
games647
c1d3f278f7 Merge pull request #520 from games647/dependabot/add-v2-config-file
Upgrade to GitHub-native Dependabot
2021-04-30 13:32:08 +02:00
dependabot-preview[bot]
7fe6d0ae2b Upgrade to GitHub-native Dependabot 2021-04-29 15:33:48 +00:00
dependabot-preview[bot]
d3be664c3d Merge pull request #517 from games647/dependabot/maven/com.mycila-license-maven-plugin-4.1 2021-04-28 07:49:29 +00:00
dependabot-preview[bot]
1edfc83e65 Merge pull request #518 from games647/dependabot/maven/junit-junit-4.13.2 2021-04-28 07:44:10 +00:00
dependabot-preview[bot]
727a16a9c0 Bump junit from 4.13.1 to 4.13.2
Bumps [junit](https://github.com/junit-team/junit4) from 4.13.1 to 4.13.2.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.13.1...r4.13.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-04-27 21:26:42 +00:00
dependabot-preview[bot]
12dccaebe8 Bump license-maven-plugin from 4.0 to 4.1
Bumps license-maven-plugin from 4.0 to 4.1.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-04-27 21:26:22 +00:00
Smart123s
0d598ad390 Moved config value checking
Previously the value for "autoLoginFloodgate" and "autoRegisterFloodgate" was checked every time a player joined.
Now they are checked at startup.
2021-04-11 11:47:56 +02:00
Smart123s
a078bb8214 Add missing return 2021-04-11 10:13:43 +02:00
games647
7192dcdf07 Merge pull request #504 from InkerBot/main
Add SodionAuthBungee support
2021-04-07 10:48:56 +02:00
墨水瓶Official
2c3fd4a575 Return when first auth plugin found 2021-04-07 00:30:11 +08:00
墨水瓶Official
ab1d3ded63 Fix errors 2021-04-07 00:12:58 +08:00
墨水瓶Official
83a6cb4bb4 Add log info and fix errors 2021-04-07 00:11:22 +08:00
InkerBot
fd045e9ed7 Add SodionAuth softDepend 2021-04-06 22:16:27 +08:00
InkerBot
fb98dd8393 Void "Hook" in plugin name 2021-04-06 22:07:26 +08:00
InkerBot
f766e6213e Use a loop to hook AuthPlugin 2021-04-06 21:58:53 +08:00
InkerBot
68d23e127a Bump SodionAuth version and fix errors. 2021-04-06 21:28:36 +08:00
InkerBot
8837a1b70e Bump SodionAuth version and fix errors. 2021-04-06 21:27:25 +08:00
dependabot-preview[bot]
9568556ceb Merge pull request #503 from games647/dependabot/maven/pl.project13.maven-git-commit-id-plugin-4.0.4 2021-04-06 13:02:28 +00:00
InkerBot
ea894b3a7b Add SodionAuthBungee hook 2021-04-06 00:31:17 +08:00
InkerBot
0c45c30d2f Bump SodionAuth version 2021-04-06 00:30:18 +08:00
dependabot-preview[bot]
17e16b68b2 Bump git-commit-id-plugin from 4.0.3 to 4.0.4
Bumps git-commit-id-plugin from 4.0.3 to 4.0.4.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-04-05 16:17:24 +00:00
games647
d6a02aa538 Apply license headers to every file
(Related #494)
2021-04-05 11:04:42 +02:00
Smart123s
9e8a9508d7 Re-use FloodgatePlayer in FloodgateAuthTask 2021-03-30 20:03:09 +02:00
Smart123s
600f484963 Added function isValidConfigValue() 2021-03-30 20:00:21 +02:00
Smart123s
94fdc70164 Update config.yml
Added Floodgate 2.0 as a requirement
Removed warning about linking accounts with "allowFloodgateNameConflict:
'false'" as it's no longer a problem with Global Linking API enabled
2021-03-29 17:15:45 +02:00
games647
c3c0827cfc Drop duplicate package goal 2021-03-29 15:19:53 +02:00
Smart123s
870d1ee281 Migrate to Floodgate v2.0
This removes support for Floodgate 1.x
2021-03-29 14:49:33 +02:00
games647
e0790965ec Catch NoSuchMethodError
Fixes #499
2021-03-29 11:56:02 +02:00
games647
4bc328c37c Fail safely if BungeeCord implementation specific classes are not found 2021-03-29 11:56:02 +02:00
games647
357430b5ad Put configuration values into extra lines to highlight the environment
They are not configuration options

Related #488
2021-03-29 11:56:02 +02:00
Smart123s
f7fd94e983 Update config comments 2021-03-22 21:25:27 +01:00
Smart123s
d8b9822c11 Fix "Asynchronous player kick" 2021-03-22 20:46:49 +01:00
Smart123s
e2e4e76fd9 Moved getGeyserPlayer() to the only class it's used in 2021-03-22 20:35:22 +01:00
Smart123s
f9992f1447 Fixed 'allowFloodgateNameConflict' for 'false' value. 2021-03-22 19:57:13 +01:00
Smart123s
5d94e610ff Create a profile for Bedrock players when registering 2021-03-22 19:51:46 +01:00
Smart123s
9abc99ebc2 Use UUID instead of name when checking for Geyser player 2021-03-22 18:37:12 +01:00
Smart123s
07da8fc76a autoRegisterFloodgate will no longer try to log in unregistered BE users
previously if autoRegisterFloodgate was set to false and the player was
not registered, the plugin tried to auto-login the user, which has led
to misleading "Failed to login" messages
2021-03-22 17:22:51 +01:00
Smart123s
305700497e Re-added an empty line (deleted by mistake) 2021-03-22 11:43:30 +01:00
Smart123s
8c8ed0b639 Made FloodgateAuth async 2021-03-22 10:16:23 +01:00
Smart123s
ee2ae7f9fd Use authPlugin.isRegistered() instead of profile.isSaved() 2021-03-21 19:21:49 +01:00
Smart123s
3e9e433736 Move dependencies 2021-03-21 11:07:18 +01:00
Smart123s
c41896e5f2 Use isPluginEnabled() in NameCheckTask.java 2021-03-21 11:02:29 +01:00
Péter Tombor
78f897a490 Use isPluginEnabled() in ConnectionListener.java
Co-authored-by: games647 <games647@users.noreply.github.com>
2021-03-21 10:59:58 +01:00
Smart123s
e1af75191e Implement autoLoginFloodgate & autoRegisterFloodgate config options
Knwon Bug: Profile.isSaved() is 'false' when logging in from Bedrock
after auto registering through Bedrock so FastLogin will try to register
for a second time, insted of logging in
2021-03-20 18:28:32 +01:00
Smart123s
a23f846146 Implement allowFloodgateNameConflict
Check config.yml for details.
2021-03-20 17:16:55 +01:00
Smart123s
0206a6c5a4 Added new config options (not yet implemented) 2021-03-20 15:37:37 +01:00
Smart123s
6544e007f6 Code cleanup 2021-03-20 14:41:21 +01:00
Smart123s
0cbf2a4e20 Check if Geyser and Floodgate are installed before accessing them 2021-03-20 13:38:41 +01:00
Smart123s
57e797f1be Implement auto login for Floodgate players
This is buggy in most cases.
2021-03-20 12:22:41 +01:00
Smart123s
e03e67b8fa Detect if a player is connecting through Floodgate
The Floodgate API requires UUID which is inaccessible at the level
FastLogion operates on.
A workaround for this is to check if the currently connecting player is
also a part of the Geyser server's online players list.
*TODO: Check for Java and Bedrock name conflicts with multiple
configurations.*
2021-03-19 08:58:29 +01:00
dependabot-preview[bot]
176781d55a Merge pull request #474 from games647/dependabot/maven/de.xxschrandxx.bca-BungeeCordAuthenticator-0.0.2 2021-03-17 15:41:41 +00:00
games647
d9f254fbff Merge pull request #473 from games647/dependabot/maven/com.comphenix.protocol-ProtocolLib-4.6.0
Bump ProtocolLib from 4.5.1 to 4.6.0
2021-03-09 20:57:41 +01:00
dependabot-preview[bot]
6b617d993f Bump BungeeCordAuthenticator from 0.0.2-SNAPSHOT to 0.0.2
Bumps BungeeCordAuthenticator from 0.0.2-SNAPSHOT to 0.0.2.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-22 16:16:07 +00:00
dependabot-preview[bot]
09ab7288da Bump ProtocolLib from 4.5.1 to 4.6.0
Bumps [ProtocolLib](https://github.com/dmulloy2/ProtocolLib) from 4.5.1 to 4.6.0.
- [Release notes](https://github.com/dmulloy2/ProtocolLib/releases)
- [Commits](https://github.com/dmulloy2/ProtocolLib/compare/4.5.1...4.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-22 16:15:32 +00:00
games647
ff2e5c0435 Drop package goal for the core module 2021-02-18 18:25:37 +01:00
games647
30c233c953 Fix workflow version 2021-02-18 18:21:32 +01:00
games647
6fd81e8e29 Sort supported list alphabetically 2021-02-18 18:17:52 +01:00
games647
4765372b0a Add BungeeAuthenticator and UserLogin 2021-02-18 18:16:06 +01:00
games647
303c064416 Check for valid file access first 2021-02-14 17:06:44 +01:00
games647
a15de80c7d Revert "Ignore the correct channel"
This reverts commit 465519ee
Namespace key class did the lowercase operation
2021-02-11 10:22:50 +01:00
games647
25356db175 Clean up CI 2021-02-09 16:33:37 +01:00
games647
465519eece Ignore the correct channel 2021-02-09 16:33:37 +01:00
games647
16f131ee2d Limit expire timer 2021-02-09 16:33:36 +01:00
games647
43046bea97 Fix branch references 2021-02-09 16:33:36 +01:00
xXSchrandXx
aa734853c6 Implement BungeeCordAuthenticator (#454)
* Create BungeeCordAuthenticatorHook

* Update bungee.yml

* Update FastLoginBungee.java

* Some small changes

* Test Hook

* Update pom.xml

* Update pom.xml

* Rebuild with new spigotplugins-repo

* Disable checksum for spigotplugins

* Update pom.xml

* Update pom.xml

* Update pom.xml

* Update pom.xml

* Update pom.xml

* Removed spigotplugins-repo

* Update pom.xml

* Update pom.xml

* Update pom.xml

* Update pom.xml

* Update pom.xml

* Update pom.xml

* Update pom.xml

New url

* Update pom.xml

* Update pom.xml

* Update FastLoginBungee.java

* requested changes

* Delete BungeeCordAuthenticator-0.0.2-SNAPSHOT.jar
2021-02-09 14:41:21 +01:00
dependabot-preview[bot]
28fb40d063 Merge pull request #453 from games647/dependabot/maven/com.zaxxer-HikariCP-4.0.1 2021-02-09 12:36:45 +00:00
games647
29c633f68a Merge pull request #459 from Kamilkime/main
Fix name change detection, allow FastLogin to respect AuthMe registration limits
2021-02-09 10:59:33 +01:00
Kamilkime
c079653d09 Always return true when registering with AuthMe 2021-02-09 10:42:10 +01:00
Kamilkime
7fbfa8240c Allow FastLogin to respect AuthMe pre IP register limit, fixes #458 2021-02-09 01:28:12 +01:00
Kamilkime
1ab346d067 Correct name check on PaperSpigot, fixes #423, fixes #437, fixes #457 2021-02-09 00:28:05 +01:00
dependabot-preview[bot]
50a8fd2f79 Bump HikariCP from 3.4.5 to 4.0.1
Bumps [HikariCP](https://github.com/brettwooldridge/HikariCP) from 3.4.5 to 4.0.1.
- [Release notes](https://github.com/brettwooldridge/HikariCP/releases)
- [Changelog](https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES)
- [Commits](https://github.com/brettwooldridge/HikariCP/compare/HikariCP-3.4.5...HikariCP-4.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-02-01 16:25:09 +00:00
games647
9ff404a424 Update CI workflow 2020-11-10 12:33:31 +01:00
games647
5029701f2a Merge pull request #418 from Kamilkime/master
Update encryption to handle MC 1.16.4, fixes #412
2020-11-09 14:38:31 +01:00
Kamilkime
1f63f91f17 Add comments, make cipher variable names clearer 2020-11-09 13:25:16 +01:00
Kamilkime
71d84d1748 Make encryption method reflections static 2020-11-08 17:15:26 +01:00
Kamilkime
64072d84d8 Update encryption to handle MC 1.16.4, fixes #412 2020-11-08 03:52:39 +01:00
dependabot-preview[bot]
f2441ecc15 Merge pull request #408 from games647/dependabot/maven/junit-junit-4.13.1 2020-11-04 11:18:44 +00:00
games647
fe1499f1fb Add support for 1.16.4
Fixes #412
Fixes #411
2020-11-04 11:05:34 +01:00
dependabot-preview[bot]
e74288e676 Bump junit from 4.13 to 4.13.1
Bumps [junit](https://github.com/junit-team/junit4) from 4.13 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.13...r4.13.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-12 16:20:06 +00:00
games647
d034e71331 Do not move and create a new proxy file
Fixes #389
2020-08-06 10:10:00 +02:00
games647
7e43b99f91 [CI-SKIP] Dump placeholderapi to prevent deprecates on register 2020-08-03 21:06:22 +02:00
games647
496a036fb4 Merge pull request #385 from ishlandbukkit/master
Add SodionAuthHook
2020-08-02 17:17:58 +02:00
games647
fa1f85698a Fix NoSuchMethodError for PlaceholderAPI after breaking change
Fixes #386
2020-07-31 17:02:51 +02:00
games647
25b6ca7653 Convert proxy file to the new name 2020-07-31 17:02:51 +02:00
games647
b30eb0de29 Debug verified username usage in ProtocolLib 2020-07-31 17:02:51 +02:00
games647
c96d64597a Clear proxies file name 2020-07-31 17:02:51 +02:00
games647
0ef2000f2a Rename rate limit to join limit 2020-07-31 17:02:51 +02:00
ishland
a36ac7f9e3 Remove unneeded SodionAuth-Libs 2020-07-29 16:11:41 +08:00
ishland
2e38550db0 I figured it out FINALLY 2020-07-29 16:07:24 +08:00
ishland
4e2b6c7810 Use JitPack and update API reference 2020-07-29 10:58:04 +08:00
ishland
4acbcbfd19 Squash previous commits
* Add SodionAuth

* Add Comment

* add SodionAuth

Co-authored-by: logos <1102280066@qq.com>
2020-07-29 09:22:17 +08:00
Gabriele C
cae2f8f58d Implement FastLoginPremiumToggleEvent 2020-06-27 13:58:38 +02:00
games647
de1487b6aa Fix driver warning message not displaying 2020-06-06 18:38:51 +02:00
games647
96cdac1332 Ignore proxied bedrock players (Fixes #328) 2020-06-06 18:32:08 +02:00
games647
2601fea84f Drop no longer needed uuid getter 2020-06-06 16:29:52 +02:00
games647
2bd339b0bf Use username from Mojang for offline IDs
Affected systems: BungeeCord after name change
Effects: Carry on items, permissions, etc. from the old user account without access to the new one

After a name change it could happen that the client still only
knows the old username and will send it to the server. Mojang will provide us with an up-to-date username that we should use instead.

The username is also sent to Mojang, so that they could verify the use. Therefore exploiting this behavior extensively for arbitrary usernames is not possible.

Related #344
2020-05-25 13:41:41 +02:00
games647
286b755ee3 Log player handling
Related #354
2020-05-23 21:40:10 +02:00
games647
5c5b7384a4 Better explain anti bot configuration values 2020-05-21 10:25:01 +02:00
games647
7c125dc0b6 Add more debugging messages for delayed proxy logins
Related #352
2020-05-21 10:03:56 +02:00
games647
103a8320ec Log requested premium logins 2020-05-20 19:50:22 +02:00
games647
49df461643 Reduce work threads, because processing is async 2020-05-19 11:47:08 +02:00
games647
3b69904257 Extract login decryption int utilities 2020-05-19 11:46:10 +02:00
games647
b41d56f835 Fix reflection access 2020-05-19 09:57:39 +02:00
games647
b1797c84d9 Prevent duplicate save requests 2020-05-18 16:10:39 +02:00
games647
9941a69c6d Use invokeExact for better performance 2020-05-18 13:21:07 +02:00
games647
0ee269785a Set UUIDs using MethodHandles 2020-05-18 12:12:51 +02:00
games647
c74c8f5fee Throw exception on unexpected UUIDs 2020-05-15 15:14:14 +02:00
games647
0ad3a853b5 Guard against any potential modifications for UUID changes
Related #344
2020-05-15 14:49:49 +02:00
games647
42637813e8 Add missing cases from last commit 2020-05-15 14:44:31 +02:00
games647
feee64309e Warn if FastLogin doesn't login authenticated players
Related #351
2020-05-15 14:38:22 +02:00
games647
b9cf8f0498 Log setting the offline UUID on Bungee
Related #344
2020-05-15 14:12:18 +02:00
games647
30a763dbc4 Add introduction about closing issues 2020-05-14 15:11:01 +02:00
games647
42790b27f8 Unregister variable on disable 2020-05-14 13:45:23 +02:00
games647
c58eda983a Fix parsing of placeholder status
Fixes #341
2020-05-14 13:41:32 +02:00
games647
477d3df1dd Favor nano time, because it's monotonic 2020-05-13 22:40:26 +02:00
games647
c1dc69845e [Experimental] Enable paranoid to hide MySQL details 2020-05-13 21:27:53 +02:00
games647
c3f6881e4b Add missing default values for the rate limiter 2020-05-13 19:51:05 +02:00
games647
25b380f74a Add a basic rate limiter for incoming connections
Related #347
2020-05-13 19:47:02 +02:00
games647
a5777869c8 Re-order driver specific properties 2020-05-13 19:46:02 +02:00
games647
cf3e8434a2 Prefer more MySQL performance optimizations 2020-05-13 19:46:02 +02:00
dependabot-preview[bot]
5881be9b78 Merge pull request #348 from games647/dependabot/maven/com.zaxxer-HikariCP-3.4.5 2020-05-12 14:22:39 +00:00
dependabot-preview[bot]
58c42f9f7f Bump HikariCP from 3.4.3 to 3.4.5
Bumps [HikariCP](https://github.com/brettwooldridge/HikariCP) from 3.4.3 to 3.4.5.
- [Release notes](https://github.com/brettwooldridge/HikariCP/releases)
- [Changelog](https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES)
- [Commits](https://github.com/brettwooldridge/HikariCP/compare/HikariCP-3.4.3...HikariCP-3.4.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-11 16:26:14 +00:00
games647
f40e787b55 Delay force action until PlayerJoinEvent is fired
Fixes Paper async chunk loading -> delayed PlayerJoinEvent
(Related #331)
2020-05-09 18:49:43 +02:00
games647
b6a95bb153 Delay force login command for async logins on Paper from Bungee
Related #331
2020-05-07 16:25:10 +02:00
dependabot-preview[bot]
9bae5c3f79 Merge pull request #339 from games647/dependabot/maven/me.clip-placeholderapi-2.10.6 2020-05-05 11:46:47 +00:00
dependabot-preview[bot]
b5ccc1df2e Bump placeholderapi from 2.10.5 to 2.10.6
Bumps placeholderapi from 2.10.5 to 2.10.6.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-04 16:26:59 +00:00
dependabot-preview[bot]
d829c71438 Merge pull request #334 from games647/dependabot/maven/com.zaxxer-HikariCP-3.4.3 2020-04-29 10:36:11 +00:00
dependabot-preview[bot]
9cf5431d1a Merge pull request #335 from games647/dependabot/maven/com.lenis0012.bukkit-loginsecurity-3.0.2 2020-04-28 08:36:50 +00:00
dependabot-preview[bot]
e0a7f207c5 Bump loginsecurity from 3.0.1 to 3.0.2
Bumps loginsecurity from 3.0.1 to 3.0.2.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-27 16:21:02 +00:00
dependabot-preview[bot]
efb4c34b50 Bump HikariCP from 3.4.2 to 3.4.3
Bumps [HikariCP](https://github.com/brettwooldridge/HikariCP) from 3.4.2 to 3.4.3.
- [Release notes](https://github.com/brettwooldridge/HikariCP/releases)
- [Changelog](https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES)
- [Commits](https://github.com/brettwooldridge/HikariCP/compare/HikariCP-3.4.2...HikariCP-3.4.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-27 16:20:09 +00:00
dependabot-preview[bot]
68d35c75c2 Bump maven-shade-plugin from 3.2.2 to 3.2.3
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.2.2...maven-shade-plugin-3.2.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-26 11:49:33 +02:00
dependabot-preview[bot]
0d93a2c371 Bump placeholderapi from 2.10.4 to 2.10.5
Bumps placeholderapi from 2.10.4 to 2.10.5.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-26 11:49:33 +02:00
games647
6091a228ab Don't rely on toString to build unique session keys
Fix IPv6 compatibility which contains brackets

Related #331
2020-04-25 17:05:08 +02:00
games647
6f99b6e9b4 Add explicit Junit dependency 2020-03-20 16:13:45 +01:00
games647
109e19e6da Add missing synchronized modifiers 2020-03-20 16:13:45 +01:00
98 changed files with 4410 additions and 598 deletions

View File

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

67
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View File

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

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
# General configuration for issue templates
# Allow issues without a template
#blank_issues_enabled: false
# Extra section on creating issues to redirect to another site
contact_links:
- name: 📌 Questions
url: https://github.com/games647/FastLogin/discussions
about: You want to ask something

View File

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

View File

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

35
.github/dependabot.yml vendored Normal file
View File

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

58
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
# GitHub automatic code security scanning using CodeQL
# Human readable name in the actions tab
name: "CodeQL"
on:
# Scan only for push on the primary branch for now
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
# job i
analyze:
# Display name
name: Analyze
# Environment
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
# Languages to scan
language: [ 'java' ]
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# Cache build process too like in the maven config
- uses: actions/cache@v2.1.4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
# Autobuild 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@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -1,11 +1,18 @@
# Human readable name
# Automatically build, run unit and integration tests to detect errors early (CI provided by GitHub)
# including making pull requests review easier
# Human readable name in the actions tab
name: Java CI
# Build on every push and pull request regardless of the branch
# Build on every pull request regardless of the branch
# Wiki: https://help.github.com/en/actions/reference/events-that-trigger-workflows
on:
- push
- pull_request
push:
branches:
- main
pull_request:
branches:
- main
jobs:
# job id
@@ -16,27 +23,32 @@ jobs:
# Run steps
steps:
# Pull changes
- uses: actions/checkout@v2
# Cache artifacts - however this has the downside that we don't get notified of
# artifact resolution failures like invalid repository
# Nevertheless the repositories should be more stable and it makes no sense to pull
# a same version every time
# A dry run would make more sense
- uses: actions/cache@v1
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v1.3.0
with:
# Use Java 8, because it's minimum required version
java-version: 8
# Build and test (included in package)
- name: Build with Maven and test
# Run non-interactive, package (with compile+test),
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums to validate posssible errors in depdendencies
run: mvn --batch-mode package --no-snapshot-updates --strict-checksums --file pom.xml
# Pull changes
- uses: actions/checkout@v2.3.4
# Cache artifacts - however this has the downside that we don't get notified of
# artifact resolution failures like invalid repository
# Nevertheless the repositories should be more stable and it makes no sense to pull
# a same version every time
# A dry run would make more sense
- uses: actions/cache@v2.1.4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v2.1.0
with:
distribution: 'adopt'
# Use Java 11, because it's minimum required version
java-version: 11
# Build and test (included in package)
- name: Build with Maven and test
# Run non-interactive, package (with compile+test),
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums to validate
# possible errors in dependencies
run: mvn test --batch-mode --no-snapshot-updates --strict-checksums --file pom.xml

5
.gitignore vendored
View File

@@ -13,6 +13,9 @@ nb-configuration.xml
*.iws
.idea/
# VSCode
.vscode/
# Maven
target/
pom.xml.versionsBackup
@@ -42,3 +45,5 @@ hs_err_pid*
# Mac filesystem dust
.DS_Store
# Factorypath from Visual Studio Code
.factorypath

View File

@@ -1,5 +1,7 @@
### 1.11
* TODO: Replace reflection with methodhandles
* Use direct proxies instead of ssl factories for multiple IP-addresses
* Remove local address check for multiple IP-addresses
* Fix parsing of local IP-addresses

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-2018
Copyright (c) 2015-2021 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,26 +11,29 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
* Cauldron support
* Forge/Sponge message support
* Premium UUID support
* Forwards Skins
* Forward skins
* Detect user name changed and will update the existing database record
* BungeeCord support
* Auto register new premium players
* Plugin: ProtocolSupport is supported and can be used as an alternative to ProtocolLib
* No client modifications needed
* Good performance by using async non blocking operations
* Good performance by using async operations
* Locale messages
* Import the database from similar plugins
* Support for Bedrock players proxied through FloodGate
## Issues
Please use issues for bug reports, suggestions, questions and more. Please check for existing issues. Existing issues
can be voted up by adding up vote to the original post. Closing issues means that they are marked as resolved. Comments
are still allowed and it could be re-opened.
## Development builds
Development builds of this project can be acquired at the provided CI (continuous integration) server. It contains the
latest changes from the Source-Code in preparation for the following release. This means they could contain new
features, bug fixes and other changes since the last release.
Development builds contain the latest changes from the Source-Code. They are bleeding edge and could introduce new bugs,
but also include features, enhancements and bug fixes that are not yet in a released version. If you click on the left
side on `Changes`, you can see iterative change sets leading to a specific build.
Nevertheless builds are only tested using a small set of automated and a few manual tests. Therefore they **could**
contain new bugs and are likely to be less stable than released versions.
https://ci.codemc.org/job/Games647/job/FastLogin/changes
You can download them from here: https://ci.codemc.org/job/Games647/job/FastLogin/
***
@@ -46,6 +49,15 @@ https://ci.codemc.org/job/Games647/job/FastLogin/changes
fastlogin.command.premium.other
fastlogin.command.cracked.other
## Placeholder
This plugin supports `PlaceholderAPI` on `Spigot`. It exports the following variable
`%fastlogin_status%`. In BungeeCord environments, the status of a player will be delivered with a delay after the player
already successful joined the server. This takes about a couple of milliseconds. In this case the value
will be `Unknown`.
Possible values: `Premium`, `Cracked`, `Unknown`
## Requirements
* Plugin:
@@ -53,22 +65,28 @@ https://ci.codemc.org/job/Games647/job/FastLogin/changes
* [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
* [Spigot](https://www.spigotmc.org) 1.8.8+
* Java 8+
* Run Spigot and/or BungeeCord/Waterfall in offline mode (see server.properties or config.yml)
* An auth plugin. Supported plugins
* Run Spigot (or a fork e.g. Paper) and/or BungeeCord (or a fork e.g. Waterfall) in offline mode
* An auth plugin.
### Bukkit/Spigot/Paper
### Supported auth plugins
#### Spigot/Paper
* [AuthMe (5.X)](https://dev.bukkit.org/bukkit-plugins/authme-reloaded/)
* [xAuth](https://dev.bukkit.org/bukkit-plugins/xauth/)
* [LogIt](https://github.com/games647/LogIt)
* [AdvancedLogin (Paid)](https://www.spigotmc.org/resources/advancedlogin.10510/)
* [AuthMe (5.X)](https://dev.bukkit.org/bukkit-plugins/authme-reloaded/)
* [CrazyLogin](https://dev.bukkit.org/bukkit-plugins/crazylogin/)
* [LoginSecurity](https://dev.bukkit.org/bukkit-plugins/loginsecurity/)
* [LogIt](https://github.com/games647/LogIt)
* [SodionAuth (2.0+)](https://github.com/MohistMC/SodionAuth)
* [UltraAuth](https://dev.bukkit.org/bukkit-plugins/ultraauth-aa/)
* [UserLogin](https://www.spigotmc.org/resources/userlogin.80669/)
* [xAuth](https://dev.bukkit.org/bukkit-plugins/xauth/)
### BungeeCord/Waterfall
#### BungeeCord/Waterfall
* [BungeeAuth](https://www.spigotmc.org/resources/bungeeauth.493/)
* [BungeeAuthenticator](https://www.spigotmc.org/resources/bungeecordauthenticator.87669/)
* [SodionAuth (2.0+)](https://github.com/MohistMC/SodionAuth)
## Network requests
@@ -81,7 +99,7 @@ This plugin performs network requests to:
## How to install
### Bukkit/Spigot/Paper
### Spigot/Paper
1. Download and install ProtocolLib/ProtocolSupport
2. Download and install FastLogin (or FastLoginBukkit for newer versions)
@@ -91,13 +109,13 @@ This plugin performs network requests to:
1. Activate BungeeCord in the Spigot configuration
2. Restart your server
3. Now there is proxy-whitelist file in the FastLogin folder
3. Now there is `allowed-proxies.txt` file in the FastLogin folder
Put your stats id from the BungeeCord config into this file
4. Activate ipForward in your BungeeCord config
5. Download and Install FastLogin (or FastLoginBungee in newer versions) on BungeeCord AND Spigot
(on the servers where your login plugin is or where player should be able to execute the commands of FastLogin)
6. Check your database settings in the config of FastLogin on BungeeCord
7. Set your proxy (BungeeCord) in offline mode by setting the value onlinemode in your config.yml to false
7. Set proxy and Spigot in offline mode by setting the value onlinemode in your config.yml to false
8. You should *always* firewall your Spigot server that it's only accessible through BungeeCord
* https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
* BungeeCord doesn't support SQLite per default, so you should change the configuration to MySQL or MariaDB

View File

@@ -1,3 +1,30 @@
<!--
SPDX-License-Identifier: MIT
The MIT License (MIT)
Copyright (c) 2015-2021 <Your name and contributors>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -20,7 +47,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<version>3.2.4</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
@@ -41,6 +68,10 @@
<pattern>com.google.gson</pattern>
<shadedPattern>fastlogin.gson</shadedPattern>
</relocation>
<relocation>
<pattern>io.papermc.lib</pattern>
<shadedPattern>fastlogin.paperlib</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
@@ -56,14 +87,10 @@
</build>
<repositories>
<!-- Bukkit-Server-API -->
<!-- PaperSpigot API and PaperLib -->
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
<!-- Disable snapshot release policy to speed up, when finding a artifact -->
<releases>
<enabled>false</enabled>
</releases>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<!-- ProtocolLib -->
@@ -98,6 +125,12 @@
<enabled>false</enabled>
</snapshots>
</repository>
<!-- Floodgate -->
<repository>
<id>nukkitx-snapshot</id>
<url>https://repo.nukkitx.com/maven-snapshots/</url>
</repository>
</repositories>
<dependencies>
@@ -108,20 +141,34 @@
<version>${project.version}</version>
</dependency>
<!--Server API-->
<!-- PaperSpigot API for correcting usercache usage -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.16.5-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- PaperLib for checking if server uses PaperSpigot -->
<dependency>
<groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId>
<version>1.0.6</version>
<scope>compile</scope>
</dependency>
<!--Library for listening and sending Minecraft packets-->
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.5.0</version>
<version>4.6.0</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Changing onlinemode on login process-->
@@ -131,13 +178,19 @@
<!--4.29.dev after commit about API improvements-->
<version>3a80c661fe</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Provide premium placeholders-->
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.10.4</version>
<version>2.10.8</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
@@ -148,6 +201,14 @@
</exclusions>
</dependency>
<!--Floodgate for Xbox Live Authentication-->
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Login Plugins-->
<dependency>
<groupId>fr.xephi</groupId>
@@ -166,7 +227,7 @@
<dependency>
<groupId>com.lenis0012.bukkit</groupId>
<artifactId>loginsecurity</artifactId>
<version>3.0.1</version>
<version>3.0.2</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
@@ -233,5 +294,19 @@
<scope>system</scope>
<systemPath>${project.basedir}/lib/UltraAuth v2.1.2.jar</systemPath>
</dependency>
<dependency>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Bukkit</artifactId>
<version>2bdfdc854b</version>
<exclusions>
<exclusion>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Libs</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit;
import com.github.games647.craftapi.model.skin.SkinProperty;
@@ -15,34 +40,32 @@ public class BukkitLoginSession extends LoginSession {
private static final byte[] EMPTY_ARRAY = {};
private final String serverId;
private final byte[] verifyToken;
private boolean verified;
private SkinProperty skinProperty;
public BukkitLoginSession(String username, String serverId, byte[] verifyToken, boolean registered
public BukkitLoginSession(String username, byte[] verifyToken, boolean registered
, StoredProfile profile) {
super(username, registered, profile);
this.serverId = serverId;
this.verifyToken = verifyToken.clone();
}
//available for BungeeCord
public BukkitLoginSession(String username, boolean registered) {
this(username, "", EMPTY_ARRAY, registered, null);
this(username, EMPTY_ARRAY, registered, null);
}
//cracked player
public BukkitLoginSession(String username, StoredProfile profile) {
this(username, "", EMPTY_ARRAY, false, profile);
this(username, EMPTY_ARRAY, false, profile);
}
//ProtocolSupport
public BukkitLoginSession(String username, boolean registered, StoredProfile profile) {
this(username, "", EMPTY_ARRAY, registered, profile);
this(username, EMPTY_ARRAY, registered, profile);
}
/**

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.core.AsyncScheduler;
@@ -11,12 +36,10 @@ import org.slf4j.Logger;
public class BukkitScheduler extends AsyncScheduler {
private final Plugin plugin;
private final Executor syncExecutor;
public BukkitScheduler(Plugin plugin, Logger logger, ThreadFactory threadFactory) {
super(logger, threadFactory);
this.plugin = plugin;
syncExecutor = r -> Bukkit.getScheduler().runTask(plugin, r);
}

View File

@@ -0,0 +1,194 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.LoginActionMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Stream;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageRecipient;
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;
private final FastLoginBukkit plugin;
private boolean enabled;
private final Set<UUID> firedJoinEvents = new HashSet<>();
public BungeeManager(FastLoginBukkit plugin) {
this.plugin = plugin;
}
public void cleanup() {
//remove old blocked status
Bukkit.getOnlinePlayers().forEach(player -> player.removeMetadata(plugin.getName(), plugin));
}
public void sendPluginMessage(PluginMessageRecipient player, ChannelMessage message) {
if (player != null) {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
message.writeTo(dataOutput);
NamespaceKey channel = new NamespaceKey(plugin.getName(), message.getChannelName());
player.sendPluginMessage(plugin, channel.getCombinedName(), dataOutput.toByteArray());
}
}
public boolean isEnabled() {
return enabled;
}
public void initialize() {
try {
enabled = detectBungeeCord();
} catch (Exception ex) {
plugin.getLog().warn("Cannot check bungeecord support. Fallback to non-bungee mode", ex);
}
if (enabled) {
proxyIds = loadBungeeCordIds();
registerPluginChannels();
}
}
private boolean detectBungeeCord() throws Exception {
try {
enabled = Class.forName("org.spigotmc.SpigotConfig").getDeclaredField("bungee").getBoolean(null);
return enabled;
} catch (ClassNotFoundException notFoundEx) {
//ignore server has no bungee support
return false;
} catch (Exception ex) {
throw ex;
}
}
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 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
*/
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.
*
* 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
* @return event fired including delay
*/
public synchronized boolean didJoinEventFired(Player player) {
return firedJoinEvents.contains(player.getUniqueId());
}
/**
* Player quit clean up
*
* @param player
*/
public synchronized void cleanup(Player player) {
firedJoinEvents.remove(player.getUniqueId());
}
}

View File

@@ -1,39 +1,63 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit;
import com.destroystokyo.paper.event.player.PlayerHandshakeEvent;
import com.github.games647.fastlogin.bukkit.command.CrackedCommand;
import com.github.games647.fastlogin.bukkit.command.PremiumCommand;
import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
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.core.CommonUtil;
import com.github.games647.fastlogin.core.PremiumStatus;
import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.LoginActionMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import io.papermc.lib.PaperLib;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.messaging.PluginMessageRecipient;
import org.slf4j.Logger;
import static com.github.games647.fastlogin.core.message.ChangePremiumMessage.CHANGE_CHANNEL;
import static com.github.games647.fastlogin.core.message.SuccessMessage.SUCCESS_CHANNEL;
/**
* This plugin checks if a player has a paid account and if so tries to skip offline mode authentication.
*/
@@ -43,12 +67,13 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
private final ConcurrentMap<String, BukkitLoginSession> loginSession = CommonUtil.buildCache(1, -1);
private final Map<UUID, PremiumStatus> premiumPlayers = new ConcurrentHashMap<>();
private final Logger logger;
private boolean serverStarted;
private boolean bungeeCord;
private final BukkitScheduler scheduler;
private boolean serverStarted;
private BungeeManager bungeeManager;
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
private PremiumPlaceholder premiumPlaceholder;
public FastLoginBukkit() {
this.logger = CommonUtil.createLoggerFromJDK(getLogger());
this.scheduler = new BukkitScheduler(this, logger, getThreadFactory());
@@ -59,34 +84,35 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
core = new FastLoginCore<>(this);
core.load();
try {
bungeeCord = Class.forName("org.spigotmc.SpigotConfig").getDeclaredField("bungee").getBoolean(null);
} catch (ClassNotFoundException notFoundEx) {
//ignore server has no bungee support
} catch (Exception ex) {
logger.warn("Cannot check bungeecord support. You use a non-Spigot build", ex);
}
if (getServer().getOnlineMode()) {
//we need to require offline to prevent a loginSession request for a offline player
logger.error("Server have to be in offline mode");
logger.error("Server has to be in offline mode");
setEnabled(false);
return;
}
// Check Floodgate config values
if (!isValidFloodgateConfigString("autoLoginFloodgate")
|| !isValidFloodgateConfigString("allowFloodgateNameConflict")) {
setEnabled(false);
return;
}
bungeeManager = new BungeeManager(this);
bungeeManager.initialize();
getServer().getPluginManager().registerEvents(new Listener() {
@EventHandler
void onHandshake(PlayerHandshakeEvent handshakeEvent) {
handshakeEvent.setCancelled(false);
handshakeEvent.setSocketAddressHostname("192.168.0.1");
}
}, this);
PluginManager pluginManager = getServer().getPluginManager();
if (bungeeCord) {
setServerStarted();
// check for incoming messages from the bungeecord version of this plugin
String forceChannel = NamespaceKey.getCombined(getName(), LoginActionMessage.FORCE_CHANNEL);
getServer().getMessenger().registerIncomingPluginChannel(this, forceChannel, new BungeeListener(this));
// outgoing
String successChannel = new NamespaceKey(getName(), SUCCESS_CHANNEL).getCombinedName();
String changeChannel = new NamespaceKey(getName(), CHANGE_CHANNEL).getCombinedName();
getServer().getMessenger().registerOutgoingPluginChannel(this, successChannel);
getServer().getMessenger().registerOutgoingPluginChannel(this, changeChannel);
if (bungeeManager.isEnabled()) {
markInitialized();
} else {
if (!core.setupDatabase()) {
setEnabled(false);
@@ -94,12 +120,18 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
}
if (pluginManager.isPluginEnabled("ProtocolSupport")) {
pluginManager.registerEvents(new ProtocolSupportListener(this), this);
pluginManager.registerEvents(new ProtocolSupportListener(this, core.getRateLimiter()), this);
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
ProtocolLibListener.register(this);
pluginManager.registerEvents(new SkinApplyListener(this), this);
ProtocolLibListener.register(this, core.getRateLimiter());
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
if (!PaperLib.isPaper() && getConfig().getBoolean("forwardSkin")) {
pluginManager.registerEvents(new SkinApplyListener(this), this);
}
} else {
logger.warn("Either ProtocolLib or ProtocolSupport have to be installed if you don't use BungeeCord");
setEnabled(false);
return;
}
}
@@ -108,14 +140,21 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
pluginManager.registerEvents(new ConnectionListener(this), this);
//if server is using paper - we need to add one more listener to correct the usercache usage
if (PaperLib.isPaper()) {
pluginManager.registerEvents(new PaperCacheListener(this), this);
}
//register commands using a unique name
getCommand("premium").setExecutor(new PremiumCommand(this));
getCommand("cracked").setExecutor(new CrackedCommand(this));
if (pluginManager.isPluginEnabled("PlaceholderAPI")) {
//prevents NoClassDef errors if it's not available
PremiumPlaceholder.register(this);
premiumPlaceholder = new PremiumPlaceholder(this);
premiumPlaceholder.register();
}
dependencyWarnings();
}
@Override
@@ -127,8 +166,14 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
core.close();
}
//remove old blacklists
getServer().getOnlinePlayers().forEach(player -> player.removeMetadata(getName(), this));
bungeeManager.cleanup();
if (premiumPlaceholder != null && getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
try {
premiumPlaceholder.unregister();
} catch (Exception | NoSuchMethodError exception) {
logger.error("Failed to unregister placeholder", exception);
}
}
}
public FastLoginCore<Player, CommandSender, FastLoginBukkit> getCore() {
@@ -145,12 +190,28 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
return loginSession;
}
public Map<UUID, PremiumStatus> getPremiumPlayers() {
return premiumPlayers;
public BukkitLoginSession getSession(InetSocketAddress addr) {
String id = getSessionId(addr);
BukkitLoginSession session = loginSession.get(id);
return session;
}
public boolean isBungeeEnabled() {
return bungeeCord;
public String getSessionId(InetSocketAddress addr) {
return addr.getAddress().getHostAddress() + ':' + addr.getPort();
}
public void putSession(InetSocketAddress addr, BukkitLoginSession session) {
String id = getSessionId(addr);
loginSession.put(id, session);
}
public void removeSession(InetSocketAddress addr) {
String id = getSessionId(addr);
loginSession.remove(id);
}
public Map<UUID, PremiumStatus> getPremiumPlayers() {
return premiumPlayers;
}
/**
@@ -159,9 +220,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
* @param onlinePlayer
* @return the online status or unknown if an error happened, the player isn't online or BungeeCord doesn't send
* us the status message yet (This means you cannot check the login status on the PlayerJoinEvent).
* @deprecated this method could be removed in future versions and exists only as a temporarily solution
*/
@Deprecated
public PremiumStatus getStatus(UUID onlinePlayer) {
return premiumPlayers.getOrDefault(onlinePlayer, PremiumStatus.UNKNOWN);
}
@@ -176,20 +235,12 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
return serverStarted;
}
public void setServerStarted() {
if (!this.serverStarted) {
this.serverStarted = true;
}
public void markInitialized() {
this.serverStarted = true;
}
public void sendPluginMessage(PluginMessageRecipient player, ChannelMessage message) {
if (player != null) {
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
message.writeTo(dataOutput);
NamespaceKey channel = new NamespaceKey(getName(), message.getChannelName());
player.sendPluginMessage(this, channel.getCombinedName(), dataOutput.toByteArray());
}
public BungeeManager getBungeeManager() {
return bungeeManager;
}
@Override
@@ -211,4 +262,61 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
public void sendMessage(CommandSender receiver, String message) {
receiver.sendMessage(message);
}
/**
* Checks if a config entry (related to Floodgate) is valid. <br>
* Writes to Log if the value is invalid.
* <p>
* This should be used for:
* <ul>
* <li>allowFloodgateNameConflict
* <li>autoLoginFloodgate
* <li>autoRegisterFloodgate
* </ul>
* </p>
*
* @param key the key of the entry in config.yml
* @return <b>true</b> if the entry's value is "true", "false", or "linked"
*/
private boolean isValidFloodgateConfigString(String key) {
String value = core.getConfig().get(key).toString().toLowerCase(Locale.ENGLISH);
if (!value.equals("true") && !value.equals("linked") && !value.equals("false") && !value.equals("no-conflict")) {
logger.error("Invalid value detected for {} in FastLogin/config.yml.", key);
return false;
}
return true;
}
/**
* Checks if a plugin is installed on the server
*
* @param name the name of the plugin
* @return true if the plugin is installed
*/
@Override
public boolean isPluginInstalled(String name) {
// the plugin may be enabled after FastLogin, so isPluginEnabled() won't work here
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
}
/**
* Send warning messages to log if incompatible plugins are used
*/
private void dependencyWarnings() {
if (isPluginInstalled("floodgate-bukkit")) {
logger.warn("We have detected that you are running Floodgate 1.0 which is not supported by the Bukkit "
+ "version of FastLogin.");
logger.warn("If you would like to use FastLogin with Floodgate, you can download development builds of "
+ "Floodgate 2.0 from https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/dev%252F2.0/");
logger.warn("Don't forget to update Geyser to a supported version as well from "
+ "https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/floodgate-2.0/");
} else if (isPluginInstalled("floodgate") && isPluginInstalled("ProtocolLib")) {
logger.warn("We have detected that you are running FastLogin alongside Floodgate and ProtocolLib.");
logger.warn("Currently there is an issue with FastLogin that prevents Floodgate's name prefixes from " +
"showing up when it is together used with ProtocolLib.");
logger.warn("If you would like to use Floodgate name prefixes, you can replace ProtocolLib with " +
"ProtocolSupport which does not have this issue.");
logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493");
}
}
}

View File

@@ -1,15 +1,37 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit;
import java.util.stream.Collectors;
import me.clip.placeholderapi.PlaceholderAPI;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.entity.Player;
import org.bukkit.OfflinePlayer;
public class PremiumPlaceholder extends PlaceholderExpansion {
private static final String PLACEHOLDER_VARIABLE = "fastlogin_status";
private static final String PLACEHOLDER_VARIABLE = "status";
private final FastLoginBukkit plugin;
@@ -17,37 +39,33 @@ public class PremiumPlaceholder extends PlaceholderExpansion {
this.plugin = plugin;
}
public static void register(FastLoginBukkit plugin) {
PremiumPlaceholder placeholderHook = new PremiumPlaceholder(plugin);
PlaceholderAPI.registerPlaceholderHook(PLACEHOLDER_VARIABLE, placeholderHook);
}
@Override
public String onPlaceholderRequest(Player player, String variable) {
if (player != null && PLACEHOLDER_VARIABLE.equals(variable)) {
return plugin.getStatus(player.getUniqueId()).name();
public String onRequest(OfflinePlayer player, String identifier) {
// player is null if offline
if (player != null && PLACEHOLDER_VARIABLE.equals(identifier)) {
return plugin.getStatus(player.getUniqueId()).getReadableName();
}
return "";
return null;
}
@Override
public String getIdentifier() {
return PLACEHOLDER_VARIABLE;
return plugin.getName();
}
@Override
public String getPlugin() {
public String getRequiredPlugin() {
return plugin.getName();
}
@Override
public String getAuthor() {
return plugin.getDescription().getAuthors().stream().collect(Collectors.joining(", "));
return String.join(", ", plugin.getDescription().getAuthors());
}
@Override
public String getVersion() {
return plugin.getName();
return plugin.getDescription().getVersion();
}
}

View File

@@ -1,11 +1,39 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.command;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPremiumToggleEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import static com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
public class CrackedCommand extends ToggleCommand {
public CrackedCommand(FastLoginBukkit plugin) {
@@ -32,7 +60,7 @@ public class CrackedCommand extends ToggleCommand {
return;
}
if (plugin.isBungeeEnabled()) {
if (plugin.getBungeeManager().isEnabled()) {
sendBungeeActivateMessage(sender, sender.getName(), false);
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
} else {
@@ -45,6 +73,8 @@ public class CrackedCommand extends ToggleCommand {
profile.setId(null);
plugin.getScheduler().runAsync(() -> {
plugin.getCore().getStorage().save(profile);
plugin.getServer().getPluginManager().callEvent(
new BukkitFastLoginPremiumToggleEvent(profile, PremiumToggleReason.COMMAND_OTHER));
});
} else {
plugin.getCore().sendLocaleMessage("not-premium", sender);
@@ -77,6 +107,8 @@ public class CrackedCommand extends ToggleCommand {
profile.setPremium(false);
plugin.getScheduler().runAsync(() -> {
plugin.getCore().getStorage().save(profile);
plugin.getServer().getPluginManager().callEvent(
new BukkitFastLoginPremiumToggleEvent(profile, PremiumToggleReason.COMMAND_OTHER));
});
}
}

View File

@@ -1,10 +1,37 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.command;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPremiumToggleEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import java.util.UUID;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -12,7 +39,7 @@ import org.bukkit.entity.Player;
/**
* Let users activate fast login by command. This only be accessible if
* the user has access to it's account. So we can make sure that not another
* person with a paid account and the same username can steal his account.
* person with a paid account and the same username can steal their account.
*/
public class PremiumCommand extends ToggleCommand {
@@ -40,27 +67,29 @@ public class PremiumCommand extends ToggleCommand {
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;
}
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);
//todo: load async
StoredProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
if (profile.isPremium()) {
plugin.getCore().sendLocaleMessage("already-exists", sender);
} else {
//todo: resolve uuid
profile.setPremium(true);
plugin.getScheduler().runAsync(() -> {
plugin.getCore().getStorage().save(profile);
});
plugin.getCore().getPendingConfirms().remove(id);
//todo: load async
StoredProfile profile = plugin.getCore().getStorage().loadProfile(sender.getName());
if (profile.isPremium()) {
plugin.getCore().sendLocaleMessage("already-exists", sender);
} else {
//todo: resolve uuid
profile.setPremium(true);
plugin.getScheduler().runAsync(() -> {
plugin.getCore().getStorage().save(profile);
plugin.getServer().getPluginManager().callEvent(
new BukkitFastLoginPremiumToggleEvent(profile, PremiumToggleReason.COMMAND_SELF));
});
plugin.getCore().sendLocaleMessage("add-premium", sender);
}
plugin.getCore().sendLocaleMessage("add-premium", sender);
}
}
private void onPremiumOther(CommandSender sender, Command command, String[] args) {
@@ -86,6 +115,8 @@ public class PremiumCommand extends ToggleCommand {
profile.setPremium(true);
plugin.getScheduler().runAsync(() -> {
plugin.getCore().getStorage().save(profile);
plugin.getServer().getPluginManager().callEvent(
new BukkitFastLoginPremiumToggleEvent(profile, PremiumToggleReason.COMMAND_OTHER));
});
plugin.getCore().sendLocaleMessage("add-premium-other", sender);

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.command;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -31,7 +56,7 @@ public abstract class ToggleCommand implements CommandExecutor {
}
protected boolean forwardBungeeCommand(CommandSender sender, String target, boolean activate) {
if (plugin.isBungeeEnabled()) {
if (plugin.getBungeeManager().isEnabled()) {
sendBungeeActivateMessage(sender, target, activate);
plugin.getCore().sendLocaleMessage("wait-on-proxy", sender);
return true;
@@ -53,7 +78,7 @@ public abstract class ToggleCommand implements CommandExecutor {
protected void sendBungeeActivateMessage(CommandSender invoker, String target, boolean activate) {
if (invoker instanceof PluginMessageRecipient) {
ChannelMessage message = new ChangePremiumMessage(target, activate, true);
plugin.sendPluginMessage((PluginMessageRecipient) invoker, message);
plugin.getBungeeManager().sendPluginMessage((PluginMessageRecipient) invoker, message);
} else {
Optional<? extends Player> optPlayer = Bukkit.getServer().getOnlinePlayers().stream().findFirst();
if (!optPlayer.isPresent()) {
@@ -63,7 +88,7 @@ public abstract class ToggleCommand implements CommandExecutor {
Player sender = optPlayer.get();
ChannelMessage message = new ChangePremiumMessage(target, activate, false);
plugin.sendPluginMessage(sender, message);
plugin.getBungeeManager().sendPluginMessage(sender, message);
}
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.event;
import com.github.games647.fastlogin.core.StoredProfile;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.event;
import com.github.games647.fastlogin.core.StoredProfile;

View File

@@ -0,0 +1,63 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class BukkitFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
private static final HandlerList handlers = new HandlerList();
private final StoredProfile profile;
private final PremiumToggleReason reason;
public BukkitFastLoginPremiumToggleEvent(StoredProfile profile, PremiumToggleReason reason) {
super(true);
this.profile = profile;
this.reason = reason;
}
@Override
public StoredProfile getProfile() {
return profile;
}
@Override
public PremiumToggleReason getReason() {
return reason;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
@@ -6,6 +31,11 @@ import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import fr.xephi.authme.api.v3.AuthMeApi;
import fr.xephi.authme.events.RestoreSessionEvent;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
import fr.xephi.authme.process.register.executors.RegistrationMethod;
import java.lang.reflect.Field;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -25,16 +55,29 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
private final FastLoginBukkit plugin;
private final AuthMeApi authmeAPI;
private Management authmeManagement;
public AuthMeHook(FastLoginBukkit plugin) {
this.plugin = plugin;
this.authmeAPI = AuthMeApi.getInstance();
if (plugin.getConfig().getBoolean("respectIpLimit", false)) {
try {
Field managementField = this.authmeAPI.getClass().getDeclaredField("management");
managementField.setAccessible(true);
this.authmeManagement = (Management) managementField.get(this.authmeAPI);
} catch (NoSuchFieldException | IllegalAccessException exception) {
this.authmeManagement = null;
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onSessionRestore(RestoreSessionEvent restoreSessionEvent) {
Player player = restoreSessionEvent.getPlayer();
String id = '/' + player.getAddress().getAddress().getHostAddress() + ':' + player.getAddress().getPort();
BukkitLoginSession session = plugin.getLoginSessions().get(id);
BukkitLoginSession session = plugin.getSession(player.spigot().getRawAddress());
if (session != null && session.isVerified()) {
restoreSessionEvent.setCancelled(true);
}
@@ -42,24 +85,32 @@ public class AuthMeHook implements AuthPlugin<Player>, Listener {
@Override
public boolean forceLogin(Player player) {
if (AuthMeApi.getInstance().isAuthenticated(player)) {
if (authmeAPI.isAuthenticated(player)) {
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
//skips registration and login
AuthMeApi.getInstance().forceLogin(player);
authmeAPI.forceLogin(player);
return true;
}
@Override
public boolean isRegistered(String playerName) {
return AuthMeApi.getInstance().isRegistered(playerName);
return authmeAPI.isRegistered(playerName);
}
@Override
//this automatically login the player too
public boolean forceRegister(Player player, String password) {
//this automatically login the player too
AuthMeApi.getInstance().forceRegister(player, password);
//if we have the management - we can trigger register with IP limit checks
if (authmeManagement != null) {
authmeManagement.performRegister(RegistrationMethod.PASSWORD_REGISTRATION,
ApiPasswordRegisterParams.of(player, password, true));
} else {
authmeAPI.forceRegister(player, password);
}
return true;
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.hook;
import com.comphenix.protocol.reflect.FieldUtils;

View File

@@ -1,5 +1,31 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import io.github.lucaseasedup.logit.CancelledState;
@@ -22,11 +48,21 @@ import org.bukkit.entity.Player;
*/
public class LogItHook implements AuthPlugin<Player> {
private final FastLoginBukkit plugin;
public LogItHook(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@Override
public boolean forceLogin(Player player) {
SessionManager sessionManager = LogItCore.getInstance().getSessionManager();
return sessionManager.isSessionAlive(player)
|| sessionManager.startSession(player) == CancelledState.NOT_CANCELLED;
if (sessionManager.isSessionAlive(player)) {
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
return sessionManager.startSession(player) == CancelledState.NOT_CANCELLED;
}
@Override

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -30,6 +55,11 @@ public class LoginSecurityHook implements AuthPlugin<Player> {
@Override
public boolean forceLogin(Player player) {
PlayerSession session = LoginSecurity.getSessionManager().getPlayerSession(player);
if (session.isAuthorized()) {
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return true;
}
return session.isAuthorized()
|| session.performAction(new LoginAction(AuthService.PLUGIN, plugin)).isSuccess();
}

View File

@@ -0,0 +1,78 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import org.bukkit.entity.Player;
import red.mohist.sodionauth.bukkit.implementation.BukkitPlayer;
import red.mohist.sodionauth.core.SodionAuthApi;
import red.mohist.sodionauth.core.exception.AuthenticatedException;
/**
* GitHub: https://github.com/Mohist-Community/SodionAuth
* <p>
* Project page: https://gitea.e-loli.com/SodionAuth/SodionAuth
* <p>
* Bukkit: Unknown
* <p>
* Spigot: https://www.spigotmc.org/resources/sodionauth.76944/
*/
public class SodionAuthHook implements AuthPlugin<Player> {
private final FastLoginBukkit plugin;
public SodionAuthHook(FastLoginBukkit plugin) {
this.plugin = plugin;
}
@Override
public boolean forceLogin(Player player) {
try {
SodionAuthApi.login(new BukkitPlayer(player));
} catch (AuthenticatedException e) {
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
return true;
}
@Override
public boolean forceRegister(Player player, String password) {
try{
return SodionAuthApi.register(new BukkitPlayer(player), password);
} catch (UnsupportedOperationException e){
plugin.getLog().warn("Currently SodionAuth is not accepting forceRegister, " +
"It may be caused by unsupported AuthBackend");
return false;
}
}
@Override
public boolean isRegistered(String playerName) {
return SodionAuthApi.isRegistered(playerName);
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -8,9 +33,7 @@ import java.util.concurrent.Future;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import ultraauth.api.UltraAuthAPI;
import ultraauth.main.Main;
import ultraauth.managers.PlayerManager;
/**
@@ -22,7 +45,6 @@ import ultraauth.managers.PlayerManager;
*/
public class UltraAuthHook implements AuthPlugin<Player> {
private final Plugin ultraAuthPlugin = Main.main;
private final FastLoginBukkit plugin;
public UltraAuthHook(FastLoginBukkit plugin) {
@@ -34,7 +56,8 @@ public class UltraAuthHook implements AuthPlugin<Player> {
//not thread-safe
Future<Boolean> future = Bukkit.getScheduler().callSyncMethod(plugin, () -> {
if (UltraAuthAPI.isAuthenticated(player)) {
return true;
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
UltraAuthAPI.authenticatedPlayer(player);

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.hook;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -35,7 +60,8 @@ public class xAuthHook implements AuthPlugin<Player> {
xAuthPlayer xAuthPlayer = xAuthPlugin.getPlayerManager().getPlayer(player);
if (xAuthPlayer != null) {
if (xAuthPlayer.isAuthenticated()) {
return true;
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
//we checked that the player is premium (paid account)

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
@@ -10,21 +35,13 @@ import com.github.games647.fastlogin.core.message.LoginActionMessage.Type;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Stream;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
import static java.util.stream.Collectors.toSet;
/**
* Responsible for receiving messages from a BungeeCord instance.
*
@@ -33,15 +50,10 @@ import static java.util.stream.Collectors.toSet;
*/
public class BungeeListener implements PluginMessageListener {
private static final String FILE_NAME = "proxy-whitelist.txt";
private final FastLoginBukkit plugin;
//null if whitelist is empty so bungeecord support is disabled
private final Set<UUID> proxyIds;
public BungeeListener(FastLoginBukkit plugin) {
this.plugin = plugin;
this.proxyIds = loadBungeeCordIds();
}
@Override
@@ -53,22 +65,25 @@ public class BungeeListener implements PluginMessageListener {
plugin.getLog().debug("Received plugin message {}", loginMessage);
//check if the player is still online or disconnected
Player checkedPlayer = Bukkit.getPlayerExact(loginMessage.getPlayerName());
if (checkedPlayer == null) {
Player targetPlayer = player;
if (!loginMessage.getPlayerName().equals(player.getName())) {
targetPlayer = Bukkit.getPlayerExact(loginMessage.getPlayerName());;
}
if (targetPlayer == null) {
plugin.getLog().warn("Force action player {} not found", loginMessage.getPlayerName());
return;
}
//fail if target player is blacklisted because already authenticated or wrong bungeecord id
if (checkedPlayer.hasMetadata(plugin.getName())) {
plugin.getLog().warn("Received message {} from a blacklisted player {}", loginMessage, checkedPlayer);
// fail if target player is blocked because already authenticated or wrong bungeecord id
if (targetPlayer.hasMetadata(plugin.getName())) {
plugin.getLog().warn("Received message {} from a blocked player {}", loginMessage, targetPlayer);
} else {
//fail if BungeeCord support is disabled (id = null)
UUID sourceId = loginMessage.getProxyId();
if (proxyIds.contains(sourceId)) {
readMessage(checkedPlayer, loginMessage);
if (plugin.getBungeeManager().isProxyAllowed(sourceId)) {
readMessage(targetPlayer, loginMessage);
} else {
plugin.getLog().warn("Received proxy id: {} that doesn't exist in the proxy whitelist file", sourceId);
plugin.getLog().warn("Received proxy id: {} that doesn't exist in the proxy file", sourceId);
}
}
}
@@ -78,52 +93,47 @@ public class BungeeListener implements PluginMessageListener {
Type type = message.getType();
InetSocketAddress address = player.getAddress();
String id = '/' + address.getAddress().getHostAddress() + ':' + address.getPort();
plugin.getLog().info("Player info {} command for {} from proxy", type, playerName);
if (type == Type.LOGIN) {
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, true);
playerSession.setVerified(true);
plugin.getLoginSessions().put(id, playerSession);
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, new ForceLoginTask(plugin.getCore(), player), 10L);
onLoginMessage(player, playerName, address);
} else if (type == Type.REGISTER) {
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> {
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
try {
//we need to check if the player is registered on Bukkit too
if (authPlugin == null || !authPlugin.isRegistered(playerName)) {
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, false);
playerSession.setVerified(true);
plugin.getLoginSessions().put(id, playerSession);
new ForceLoginTask(plugin.getCore(), player).run();
}
} catch (Exception ex) {
plugin.getLog().error("Failed to query isRegistered for player: {}", player, ex);
}
}, 10L);
onRegisterMessage(player, playerName, address);
} else if (type == Type.CRACKED) {
//we don't start a force login task here so update it manually
plugin.getPremiumPlayers().put(player.getUniqueId(), PremiumStatus.CRACKED);
}
}
public Set<UUID> loadBungeeCordIds() {
Path whitelistFile = plugin.getPluginFolder().resolve(FILE_NAME);
try {
if (Files.notExists(whitelistFile)) {
Files.createFile(whitelistFile);
}
private void onLoginMessage(Player player, String playerName, InetSocketAddress address) {
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, true);
startLoginTaskIfReady(player, playerSession);
}
try (Stream<String> lines = Files.lines(whitelistFile)) {
return lines.map(String::trim)
.map(UUID::fromString)
.collect(toSet());
private void onRegisterMessage(Player player, String playerName, InetSocketAddress address) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
try {
//we need to check if the player is registered on Bukkit too
if (authPlugin == null || !authPlugin.isRegistered(playerName)) {
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, false);
startLoginTaskIfReady(player, playerSession);
}
} catch (Exception ex) {
plugin.getLog().error("Failed to query isRegistered for player: {}", player, ex);
}
} catch (IOException ex) {
plugin.getLog().error("Failed to create file for Proxy whitelist", ex);
} catch (Exception ex) {
plugin.getLog().error("Failed to retrieve proxy Id. Disabling BungeeCord support", ex);
});
}
private void startLoginTaskIfReady(Player player, BukkitLoginSession session) {
session.setVerified(true);
plugin.putSession(player.spigot().getRawAddress(), session);
// only start a new login task if the join event fired earlier. This event then didn
boolean result = plugin.getBungeeManager().didJoinEventFired(player);
plugin.getLog().info("Delaying force login until join event fired?: {}", result);
if (result) {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
}
return Collections.emptySet();
}
}

View File

@@ -1,6 +1,33 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask;
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
import org.bukkit.Bukkit;
@@ -11,6 +38,8 @@ 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.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.bukkit.event.player.PlayerQuitEvent;
/**
@@ -29,6 +58,7 @@ public class ConnectionListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerLogin(PlayerLoginEvent loginEvent) {
removeBlockedStatus(loginEvent.getPlayer());
if (loginEvent.getResult() == Result.ALLOWED && !plugin.isServerFullyStarted()) {
loginEvent.disallow(Result.KICK_OTHER, plugin.getCore().getMessage("not-started"));
}
@@ -38,24 +68,49 @@ public class ConnectionListener implements Listener {
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
Player player = joinEvent.getPlayer();
removeBlacklistStatus(player);
if (!plugin.isBungeeEnabled()) {
//Wait before auth plugin and we received a message from BungeeCord initializes the player
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player);
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, forceLoginTask, DELAY_LOGIN);
}
Bukkit.getScheduler().runTaskLater(plugin, () -> {
// 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());
boolean isFloodgateLogin = false;
if (Bukkit.getServer().getPluginManager().isPluginEnabled("floodgate")) {
FloodgatePlayer floodgatePlayer = FloodgateApi.getInstance().getPlayer(player.getUniqueId());
if (floodgatePlayer != null) {
isFloodgateLogin = true;
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);
}
}
if (!isFloodgateLogin) {
if (session == null) {
String sessionId = plugin.getSessionId(player.spigot().getRawAddress());
plugin.getLog().info("No on-going login session for player: {} with ID {}", player, sessionId);
} else {
Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask);
}
}
plugin.getBungeeManager().markJoinEventFired(player);
// delay the login process to let auth plugins initialize the player
// Magic number however as there is no direct event from those plugins
}, DELAY_LOGIN);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent quitEvent) {
Player player = quitEvent.getPlayer();
removeBlacklistStatus(player);
removeBlockedStatus(player);
plugin.getCore().getPendingConfirms().remove(player.getUniqueId());
plugin.getPremiumPlayers().remove(player.getUniqueId());
plugin.getBungeeManager().cleanup(player);
}
private void removeBlacklistStatus(Player player) {
private void removeBlockedStatus(Player player) {
player.removeMetadata(plugin.getName(), plugin);
}
}

View File

@@ -0,0 +1,66 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener;
import com.destroystokyo.paper.profile.ProfileProperty;
import com.github.games647.craftapi.model.skin.Textures;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
public class PaperCacheListener implements Listener {
private final FastLoginBukkit plugin;
public PaperCacheListener(final FastLoginBukkit plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.HIGHEST)
//if paper is used - player skin must be set at pre login, otherwise usercache is used
//using usercache makes premium name change basically impossible
public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent event) {
if (event.getLoginResult() != Result.ALLOWED) {
return;
}
// event gives us only IP, not the port, so we need to loop through all the sessions
for (BukkitLoginSession session : plugin.getLoginSessions().values()) {
if (!event.getName().equals(session.getUsername())) {
continue;
}
session.getSkin().ifPresent(skin -> event.getPlayerProfile().setProperty(new ProfileProperty(Textures.KEY,
skin.getValue(), skin.getSignature())));
break;
}
}
}

View File

@@ -1,16 +1,40 @@
package com.github.games647.fastlogin.bukkit;
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
@@ -27,7 +51,7 @@ public class EncryptionUtil {
public static final String KEY_PAIR_ALGORITHM = "RSA";
private EncryptionUtil() {
//utility
// utility
}
/**
@@ -36,13 +60,14 @@ public class EncryptionUtil {
* @return The RSA key pair.
*/
public static KeyPair generateKeyPair() {
// KeyPair b()
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALGORITHM);
keyPairGenerator.initialize(1_024);
return keyPairGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException nosuchalgorithmexception) {
//Should be existing in every vm
// Should be existing in every vm
throw new ExceptionInInitializerError(nosuchalgorithmexception);
}
}
@@ -55,6 +80,7 @@ public class EncryptionUtil {
* @return an error with 4 bytes long
*/
public static byte[] generateVerifyToken(Random random) {
// extracted from LoginListener
byte[] token = new byte[VERIFY_TOKEN_LENGTH];
random.nextBytes(token);
return token;
@@ -63,14 +89,15 @@ public class EncryptionUtil {
/**
* Generate the server id based on client and server data.
*
* @param sessionId session for the current login attempt
* @param sessionId session for the current login attempt
* @param sharedSecret shared secret between the client and the server
* @param publicKey public key of the server
* @param publicKey public key of the server
* @return the server id formatted as a hexadecimal string.
*/
public static String getServerIdHashString(String sessionId, Key sharedSecret, PublicKey publicKey) {
public static String getServerIdHashString(String sessionId, SecretKey sharedSecret, PublicKey publicKey) {
// found in LoginListener
try {
byte[] serverHash = getServerIdHash(sessionId, sharedSecret, publicKey);
byte[] serverHash = getServerIdHash(sessionId, publicKey, sharedSecret);
return (new BigInteger(serverHash)).toString(16);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
@@ -82,31 +109,44 @@ public class EncryptionUtil {
/**
* Decrypts the content and extracts the key spec.
*
* @param cipher decryption cipher initialized with the private key
* @param sharedKey the encrypted shared key
* @param privateKey private server key
* @param sharedKey the encrypted shared key
* @return shared secret key
* @throws GeneralSecurityException if it fails to decrypt the data
*/
public static SecretKey decryptSharedKey(Cipher cipher, byte[] sharedKey) throws GeneralSecurityException {
return new SecretKeySpec(decrypt(cipher, sharedKey), "AES");
public static SecretKey decryptSharedKey(PrivateKey privateKey, byte[] sharedKey) throws GeneralSecurityException {
// SecretKey a(PrivateKey var0, byte[] var1)
return new SecretKeySpec(decrypt(privateKey, sharedKey), "AES");
}
public static byte[] decrypt(PrivateKey key, byte[] data) throws GeneralSecurityException {
// b(Key var0, byte[] var1)
Cipher cipher = Cipher.getInstance(key.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, key);
return decrypt(cipher, data);
}
/**
* Decrypted the given data using the cipher.
*
* @param cipher decryption cypher initialized with the private key
* @param data the encrypted data
* @param data the encrypted data
* @return clear text data
* @throws GeneralSecurityException if it fails to decrypt the data
*/
public static byte[] decrypt(Cipher cipher, byte[] data) throws GeneralSecurityException {
private static byte[] decrypt(Cipher cipher, byte[] data) throws GeneralSecurityException {
// inlined: byte[] a(int var0, Key var1, byte[] var2), Cipher a(int var0, String var1, Key
// var2)
return cipher.doFinal(data);
}
private static byte[] getServerIdHash(String sessionId, Key sharedSecret, PublicKey publicKey)
private static byte[] getServerIdHash(
String sessionId, PublicKey publicKey, SecretKey sharedSecret)
throws NoSuchAlgorithmException {
// byte[] a(String var0, PublicKey var1, SecretKey var2)
MessageDigest digest = MessageDigest.getInstance("SHA-1");
// inlined from byte[] a(String var0, byte[]... var1)
digest.update(sessionId.getBytes(StandardCharsets.ISO_8859_1));
digest.update(sharedSecret.getEncoded());
digest.update(publicKey.getEncoded());

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
@@ -7,11 +32,11 @@ import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.event.BukkitFastLoginPreLoginEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import java.security.PublicKey;
import java.util.Random;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -27,8 +52,8 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
private final Player player;
private final String username;
public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random,
Player player, String username, PublicKey publicKey) {
public NameCheckTask(FastLoginBukkit plugin, Random random, Player player, PacketEvent packetEvent,
String username, PublicKey publicKey) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
this.plugin = plugin;
@@ -42,14 +67,15 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
@Override
public void run() {
try {
super.onLogin(username, new ProtocolLibLoginSource(packetEvent, player, random, publicKey));
super.onLogin(username, new ProtocolLibLoginSource(player, random, publicKey));
} finally {
ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
}
}
@Override
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLibLoginSource source, StoredProfile profile) {
public FastLoginPreLoginEvent callFastLoginPreLoginEvent(String username, ProtocolLibLoginSource source,
StoredProfile profile) {
BukkitFastLoginPreLoginEvent event = new BukkitFastLoginPreLoginEvent(username, source, profile);
plugin.getServer().getPluginManager().callEvent(event);
return event;
@@ -61,7 +87,7 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
public void requestPremiumLogin(ProtocolLibLoginSource source, StoredProfile profile
, String username, boolean registered) {
try {
source.setOnlineMode();
source.enableOnlinemode();
} catch (Exception ex) {
plugin.getLog().error("Cannot send encryption packet. Falling back to cracked login for: {}", profile, ex);
return;
@@ -70,11 +96,10 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
String ip = player.getAddress().getAddress().getHostAddress();
core.getPendingLogin().put(ip + username, new Object());
String serverId = source.getServerId();
byte[] verify = source.getVerifyToken();
BukkitLoginSession playerSession = new BukkitLoginSession(username, serverId, verify, registered, profile);
plugin.getLoginSessions().put(player.getAddress().toString(), playerSession);
BukkitLoginSession playerSession = new BukkitLoginSession(username, verify, registered, profile);
plugin.putSession(player.getAddress(), playerSession);
//cancel only if the player has a paid account otherwise login as normal offline player
synchronized (packetEvent.getAsyncMarker().getProcessingLock()) {
packetEvent.setCancelled(true);
@@ -84,6 +109,6 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
@Override
public void startCrackedSession(ProtocolLibLoginSource source, StoredProfile profile, String username) {
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
plugin.getLoginSessions().put(player.getAddress().toString(), loginSession);
plugin.putSession(player.getAddress(), loginSession);
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
import com.comphenix.protocol.PacketType;
@@ -5,8 +30,8 @@ import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.github.games647.fastlogin.bukkit.EncryptionUtil;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.RateLimiter;
import java.security.KeyPair;
import java.security.SecureRandom;
@@ -18,15 +43,16 @@ import static com.comphenix.protocol.PacketType.Login.Client.START;
public class ProtocolLibListener extends PacketAdapter {
private static final int WORKER_THREADS = 3;
public static final String SOURCE_META_KEY = "source";
private final FastLoginBukkit plugin;
//just create a new once on plugin enable. This used for verify token generation
private final SecureRandom random = new SecureRandom();
private final KeyPair keyPair = EncryptionUtil.generateKeyPair();
private final RateLimiter rateLimiter;
public ProtocolLibListener(FastLoginBukkit plugin) {
public ProtocolLibListener(FastLoginBukkit plugin, RateLimiter rateLimiter) {
//run async in order to not block the server, because we are making api calls to Mojang
super(params()
.plugin(plugin)
@@ -34,33 +60,51 @@ public class ProtocolLibListener extends PacketAdapter {
.optionAsync());
this.plugin = plugin;
this.rateLimiter = rateLimiter;
}
public static void register(FastLoginBukkit plugin) {
//they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
public static void register(FastLoginBukkit plugin, RateLimiter rateLimiter) {
// they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError
// TODO: make synchronous processing, but do web or database requests async
ProtocolLibrary.getProtocolManager()
.getAsynchronousManager()
.registerAsyncHandler(new ProtocolLibListener(plugin))
.start(WORKER_THREADS);
.registerAsyncHandler(new ProtocolLibListener(plugin, rateLimiter))
.start();
}
@Override
public void onPacketReceiving(PacketEvent packetEvent) {
if (packetEvent.isCancelled()
|| plugin.getCore().getAuthPluginHook()== null
|| plugin.getCore().getAuthPluginHook() == null
|| !plugin.isServerFullyStarted()) {
return;
}
if (isFastLoginPacket(packetEvent)) {
// this is our own packet
return;
}
Player sender = packetEvent.getPlayer();
PacketType packetType = packetEvent.getPacketType();
if (packetType == START) {
if (!rateLimiter.tryAcquire()) {
plugin.getLog().warn("Simple Anti-Bot join limit - Ignoring {}", sender);
return;
}
onLogin(packetEvent, sender);
} else {
onEncryptionBegin(packetEvent, sender);
}
}
private Boolean isFastLoginPacket(PacketEvent packetEvent) {
return packetEvent.getPacket().getMeta(SOURCE_META_KEY)
.map(val -> val.equals(plugin.getName()))
.orElse(false);
}
private void onEncryptionBegin(PacketEvent packetEvent, Player sender) {
byte[] sharedSecret = packetEvent.getPacket().getByteArrays().read(0);
@@ -74,7 +118,7 @@ public class ProtocolLibListener extends PacketAdapter {
String sessionKey = player.getAddress().toString();
//remove old data every time on a new login in order to keep the session only for one person
plugin.getLoginSessions().remove(sessionKey);
plugin.removeSession(player.getAddress());
//player.getName() won't work at this state
PacketContainer packet = packetEvent.getPacket();
@@ -83,7 +127,7 @@ public class ProtocolLibListener extends PacketAdapter {
plugin.getLog().trace("GameProfile {} with {} connecting", sessionKey, username);
packetEvent.getAsyncMarker().incrementProcessingDelay();
Runnable nameCheckTask = new NameCheckTask(plugin, packetEvent, random, player, username, keyPair.getPublic());
Runnable nameCheckTask = new NameCheckTask(plugin, random, player, packetEvent, username, keyPair.getPublic());
plugin.getScheduler().runAsync(nameCheckTask);
}
}

View File

@@ -1,11 +1,35 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.github.games647.fastlogin.bukkit.EncryptionUtil;
import com.github.games647.fastlogin.core.shared.LoginSource;
import java.lang.reflect.InvocationTargetException;
@@ -19,9 +43,8 @@ import org.bukkit.entity.Player;
import static com.comphenix.protocol.PacketType.Login.Server.DISCONNECT;
import static com.comphenix.protocol.PacketType.Login.Server.ENCRYPTION_BEGIN;
public class ProtocolLibLoginSource implements LoginSource {
class ProtocolLibLoginSource implements LoginSource {
private final PacketEvent packetEvent;
private final Player player;
private final Random random;
@@ -30,15 +53,14 @@ public class ProtocolLibLoginSource implements LoginSource {
private final String serverId = "";
private byte[] verifyToken;
public ProtocolLibLoginSource(PacketEvent packetEvent, Player player, Random random, PublicKey publicKey) {
this.packetEvent = packetEvent;
public ProtocolLibLoginSource(Player player, Random random, PublicKey publicKey) {
this.player = player;
this.random = random;
this.publicKey = publicKey;
}
@Override
public void setOnlineMode() throws Exception {
public void enableOnlinemode() throws Exception {
verifyToken = EncryptionUtil.generateVerifyToken(random);
/*
@@ -49,9 +71,17 @@ public class ProtocolLibLoginSource implements LoginSource {
PacketContainer newPacket = new PacketContainer(ENCRYPTION_BEGIN);
newPacket.getStrings().write(0, serverId);
newPacket.getSpecificModifier(PublicKey.class).write(0, publicKey);
StructureModifier<PublicKey> keyModifier = newPacket.getSpecificModifier(PublicKey.class);
int verifyField = 0;
if (keyModifier.getFields().isEmpty()) {
// Since 1.16.4 this is now a byte field
newPacket.getByteArrays().write(0, publicKey.getEncoded());
verifyField++;
} else {
keyModifier.write(0, publicKey);
}
newPacket.getByteArrays().write(0, verifyToken);
newPacket.getByteArrays().write(verifyField, verifyToken);
//serverId is a empty string
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket);
@@ -76,7 +106,7 @@ public class ProtocolLibLoginSource implements LoginSource {
@Override
public InetSocketAddress getAddress() {
return packetEvent.getPlayer().getAddress();
return player.getAddress();
}
public String getServerId() {
@@ -90,8 +120,7 @@ public class ProtocolLibLoginSource implements LoginSource {
@Override
public String toString() {
return this.getClass().getSimpleName() + '{' +
"packetEvent=" + packetEvent +
", player=" + player +
"player=" + player +
", random=" + random +
", serverId='" + serverId + '\'' +
", verifyToken=" + Arrays.toString(verifyToken) +

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
import com.comphenix.protocol.reflect.MethodUtils;
@@ -9,9 +34,6 @@ import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.github.games647.craftapi.model.skin.Textures;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import java.lang.reflect.InvocationTargetException;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -19,6 +41,8 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
import java.lang.reflect.InvocationTargetException;
public class SkinApplyListener implements Listener {
private static final Class<?> GAME_PROFILE = MinecraftReflection.getGameProfileClass();
@@ -39,14 +63,12 @@ public class SkinApplyListener implements Listener {
Player player = loginEvent.getPlayer();
if (plugin.getConfig().getBoolean("forwardSkin")) {
//go through every session, because player.getAddress is null
//loginEvent.getAddress is just a InetAddress not InetSocketAddress, so not unique enough
for (BukkitLoginSession session : plugin.getLoginSessions().values()) {
if (session.getUsername().equals(player.getName())) {
session.getSkin().ifPresent(skin -> applySkin(player, skin.getValue(), skin.getSignature()));
break;
}
//go through every session, because player.getAddress is null
//loginEvent.getAddress is just a InetAddress not InetSocketAddress, so not unique enough
for (BukkitLoginSession session : plugin.getLoginSessions().values()) {
if (session.getUsername().equals(player.getName())) {
session.getSkin().ifPresent(skin -> applySkin(player, skin.getValue(), skin.getSignature()));
break;
}
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
import com.comphenix.protocol.ProtocolLibrary;
@@ -6,13 +31,13 @@ import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.server.TemporaryPlayerFactory;
import com.comphenix.protocol.reflect.FieldUtils;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.github.games647.craftapi.model.auth.Verification;
import com.github.games647.craftapi.model.skin.SkinProperty;
import com.github.games647.craftapi.resolver.MojangResolver;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.EncryptionUtil;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import java.io.IOException;
@@ -21,6 +46,7 @@ import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.util.Arrays;
@@ -37,6 +63,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 final FastLoginBukkit plugin;
private final PacketEvent packetEvent;
private final KeyPair serverKey;
@@ -45,6 +78,9 @@ public class VerifyResponseTask implements Runnable {
private final byte[] sharedSecret;
private static Method encryptMethod;
private static Method cipherMethod;
public VerifyResponseTask(FastLoginBukkit plugin, PacketEvent packetEvent, Player player,
byte[] sharedSecret, KeyPair keyPair) {
this.plugin = plugin;
@@ -57,7 +93,7 @@ public class VerifyResponseTask implements Runnable {
@Override
public void run() {
try {
BukkitLoginSession session = plugin.getLoginSessions().get(player.getAddress().toString());
BukkitLoginSession session = plugin.getSession(player.getAddress());
if (session == null) {
disconnect("invalid-request", true
, "GameProfile {0} tried to send encryption response at invalid state", player.getAddress());
@@ -77,20 +113,16 @@ public class VerifyResponseTask implements Runnable {
private void verifyResponse(BukkitLoginSession session) {
PrivateKey privateKey = serverKey.getPrivate();
Cipher cipher;
SecretKey loginKey;
try {
cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
loginKey = EncryptionUtil.decryptSharedKey(cipher, sharedSecret);
loginKey = EncryptionUtil.decryptSharedKey(privateKey, sharedSecret);
} catch (GeneralSecurityException securityEx) {
disconnect("error-kick", false, "Cannot decrypt received contents", securityEx);
return;
}
try {
if (!checkVerifyToken(session, cipher, privateKey) || !encryptConnection(loginKey)) {
if (!checkVerifyToken(session) || !enableEncryption(loginKey)) {
return;
}
} catch (Exception ex) {
@@ -100,30 +132,37 @@ public class VerifyResponseTask implements Runnable {
String serverId = EncryptionUtil.getServerIdHashString("", loginKey, serverKey.getPublic());
String username = session.getUsername();
String requestedUsername = session.getRequestUsername();
InetSocketAddress socketAddress = player.getAddress();
try {
MojangResolver resolver = plugin.getCore().getResolver();
InetAddress address = socketAddress.getAddress();
Optional<Verification> response = resolver.hasJoined(username, serverId, address);
Optional<Verification> response = resolver.hasJoined(requestedUsername, serverId, address);
if (response.isPresent()) {
plugin.getLog().info("GameProfile {} has a verified premium account", username);
Verification verification = response.get();
plugin.getLog().info("Profile {} has a verified premium account", requestedUsername);
String realUsername = verification.getName();
if (realUsername == null) {
disconnect("invalid-session", true, "Username field null for {}", requestedUsername);
return;
}
SkinProperty[] properties = response.get().getProperties();
SkinProperty[] properties = verification.getProperties();
if (properties.length > 0) {
session.setSkinProperty(properties[0]);
}
session.setUuid(response.get().getId());
session.setVerifiedUsername(realUsername);
session.setUuid(verification.getId());
session.setVerified(true);
setPremiumUUID(session.getUuid());
receiveFakeStartPacket(username);
receiveFakeStartPacket(realUsername);
} else {
//user tried to fake a authentication
disconnect("invalid-session", true
, "GameProfile {0} ({1}) tried to log in with an invalid session ServerId: {2}"
, session.getUsername(), socketAddress, serverId);
, session.getRequestUsername(), socketAddress, serverId);
}
} catch (IOException ioEx) {
disconnect("error-kick", false, "Failed to connect to session server", ioEx);
@@ -142,18 +181,17 @@ public class VerifyResponseTask implements Runnable {
}
}
private boolean checkVerifyToken(BukkitLoginSession session, Cipher cipher, PrivateKey privateKey)
throws GeneralSecurityException {
private boolean checkVerifyToken(BukkitLoginSession session) throws GeneralSecurityException {
byte[] requestVerify = session.getVerifyToken();
//encrypted verify token
byte[] responseVerify = packetEvent.getPacket().getByteArrays().read(1);
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L182
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(cipher, responseVerify))) {
//check if the verify token are equal to the server sent one
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(serverKey.getPrivate(), responseVerify))) {
//check if the verify-token are equal to the server sent one
disconnect("invalid-verify-token", true
, "GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}"
, session.getUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
, session.getRequestUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
return false;
}
@@ -164,24 +202,48 @@ public class VerifyResponseTask implements Runnable {
private Object getNetworkManager() throws IllegalAccessException, ClassNotFoundException {
Object injectorContainer = TemporaryPlayerFactory.getInjectorFromPlayer(player);
//ChannelInjector
// ChannelInjector
Class<?> injectorClass = Class.forName("com.comphenix.protocol.injector.netty.Injector");
Object rawInjector = FuzzyReflection.getFieldValue(injectorContainer, injectorClass, true);
return FieldUtils.readField(rawInjector, "networkManager", true);
}
private boolean encryptConnection(SecretKey loginKey) throws IllegalArgumentException {
private boolean enableEncryption(SecretKey loginKey) throws IllegalArgumentException {
plugin.getLog().info("Enabling onlinemode encryption for {}", player.getAddress());
// Initialize method reflections
if (encryptMethod == null) {
Class<?> networkManagerClass = MinecraftReflection.getNetworkManagerClass();
try {
// Try to get the old (pre MC 1.16.4) encryption method
encryptMethod = 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);
// Get the needed Cipher helper method (used to generate ciphers from login key)
cipherMethod = FuzzyReflection.fromClass(ENCRYPTION_CLASS)
.getMethodByParameters("a", int.class, Key.class);
}
}
try {
//get the NMS connection handle of this player
Object networkManager = getNetworkManager();
Object networkManager = this.getNetworkManager();
//try to detect the method by parameters
Method encryptMethod = FuzzyReflection
.fromObject(networkManager).getMethodByParameters("a", SecretKey.class);
// If cipherMethod is null - use old encryption (pre MC 1.16.4), otherwise use the new cipher one
if (cipherMethod == null) {
// Encrypt/decrypt packet flow, this behaviour is expected by the client
encryptMethod.invoke(networkManager, loginKey);
} else {
// Create ciphers from login key
Object decryptionCipher = cipherMethod.invoke(null, Cipher.DECRYPT_MODE, loginKey);
Object encryptionCipher = cipherMethod.invoke(null, Cipher.ENCRYPT_MODE, loginKey);
//encrypt/decrypt following packets
//the client expects this behaviour
encryptMethod.invoke(networkManager, loginKey);
// Encrypt/decrypt packet flow, this behaviour is expected by the client
encryptMethod.invoke(networkManager, decryptionCipher, encryptionCipher);
}
} catch (Exception ex) {
disconnect("error-kick", false, "Couldn't enable encryption", ex);
return false;
@@ -224,7 +286,8 @@ public class VerifyResponseTask implements Runnable {
startPacket.getGameProfiles().write(0, fakeProfile);
try {
//we don't want to handle our own packets so ignore filters
ProtocolLibrary.getProtocolManager().recieveClientPacket(player, startPacket, false);
startPacket.setMeta(ProtocolLibListener.SOURCE_META_KEY, plugin.getName());
ProtocolLibrary.getProtocolManager().recieveClientPacket(player, startPacket, true);
} catch (InvocationTargetException | IllegalAccessException ex) {
plugin.getLog().warn("Failed to fake a new start packet for: {}", username, ex);
//cancel the event in order to prevent the server receiving an invalid packet

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocolsupport;
import com.github.games647.fastlogin.core.shared.LoginSource;
@@ -15,7 +40,7 @@ public class ProtocolLoginSource implements LoginSource {
}
@Override
public void setOnlineMode() {
public void enableOnlinemode() {
loginStartEvent.setOnlineMode(true);
}
@@ -26,7 +51,7 @@ public class ProtocolLoginSource implements LoginSource {
@Override
public InetSocketAddress getAddress() {
return loginStartEvent.getAddress();
return loginStartEvent.getConnection().getRawAddress();
}
public PlayerLoginStartEvent getLoginStartEvent() {

View File

@@ -1,20 +1,47 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name 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.RateLimiter;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.JoinManagement;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import java.net.InetSocketAddress;
import java.util.Optional;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
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;
@@ -23,11 +50,13 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
implements Listener {
private final FastLoginBukkit plugin;
private final RateLimiter rateLimiter;
public ProtocolSupportListener(FastLoginBukkit plugin) {
public ProtocolSupportListener(FastLoginBukkit plugin, RateLimiter rateLimiter) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
this.plugin = plugin;
this.rateLimiter = rateLimiter;
}
@EventHandler
@@ -36,25 +65,32 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
return;
}
if (!rateLimiter.tryAcquire()) {
plugin.getLog().warn("Simple Anti-Bot join limit - Ignoring {}", loginStartEvent.getConnection());
return;
}
String username = loginStartEvent.getConnection().getProfile().getName();
InetSocketAddress address = loginStartEvent.getAddress();
InetSocketAddress address = loginStartEvent.getConnection().getRawAddress();
//remove old data every time on a new login in order to keep the session only for one person
plugin.getLoginSessions().remove(address.toString());
plugin.removeSession(address);
super.onLogin(username, new ProtocolLoginSource(loginStartEvent));
ProtocolLoginSource source = new ProtocolLoginSource(loginStartEvent);
super.onLogin(username, source);
}
@EventHandler
public void onConnectionClosed(ConnectionCloseEvent closeEvent) {
InetSocketAddress address = closeEvent.getConnection().getAddress();
plugin.getLoginSessions().remove(address.toString());
InetSocketAddress address = closeEvent.getConnection().getRawAddress();
plugin.removeSession(address);
}
@EventHandler
public void onPropertiesResolve(PlayerProfileCompleteEvent profileCompleteEvent) {
InetSocketAddress address = profileCompleteEvent.getAddress();
BukkitLoginSession session = plugin.getLoginSessions().get(address.toString());
InetSocketAddress address = profileCompleteEvent.getConnection().getRawAddress();
BukkitLoginSession session = plugin.getSession(address);
if (session != null && profileCompleteEvent.getConnection().getProfile().isOnlineMode()) {
session.setVerified(true);
@@ -77,21 +113,18 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
@Override
public void requestPremiumLogin(ProtocolLoginSource source, StoredProfile profile, String username
, boolean registered) {
source.setOnlineMode();
source.enableOnlinemode();
String ip = source.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogin().put(ip + username, new Object());
BukkitLoginSession playerSession = new BukkitLoginSession(username, registered, profile);
plugin.getLoginSessions().put(source.getAddress().toString(), playerSession);
if (plugin.getConfig().getBoolean("premiumUuid")) {
source.getLoginStartEvent().setOnlineMode(true);
}
plugin.putSession(source.getAddress(), playerSession);
}
@Override
public void startCrackedSession(ProtocolLoginSource source, StoredProfile profile, String username) {
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
plugin.getLoginSessions().put(source.getAddress().toString(), loginSession);
plugin.putSession(source.getAddress(), loginSession);
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.task;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
@@ -7,6 +32,7 @@ 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.bukkit.hook.SodionAuthHook;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import java.lang.reflect.Constructor;
@@ -28,7 +54,7 @@ public class DelayedAuthHook implements Runnable {
@Override
public void run() {
boolean hookFound = isHookFound();
if (plugin.isBungeeEnabled()) {
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 "
@@ -38,7 +64,7 @@ public class DelayedAuthHook implements Runnable {
}
if (hookFound) {
plugin.setServerStarted();
plugin.markInitialized();
}
}
@@ -68,13 +94,13 @@ public class DelayedAuthHook implements Runnable {
private AuthPlugin<Player> getAuthHook() {
try {
@SuppressWarnings("unchecked")
List<Class<? extends AuthPlugin<Player>>> hooks = Arrays.asList(AuthMeHook.class,
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class, UltraAuthHook.class,
xAuthHook.class);
CrazyLoginHook.class, LogItHook.class, LoginSecurityHook.class,
SodionAuthHook.class, UltraAuthHook.class, xAuthHook.class);
for (Class<? extends AuthPlugin<Player>> clazz : hooks) {
String pluginName = clazz.getSimpleName().replace("Hook", "");
String pluginName = clazz.getSimpleName();
pluginName = pluginName.substring(0, pluginName.length() - "Hook".length());
//uses only member classes which uses AuthPlugin interface (skip interfaces)
if (Bukkit.getPluginManager().isPluginEnabled(pluginName)) {
//check only for enabled plugins. A single plugin could be disabled by plugin managers

View File

@@ -0,0 +1,72 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.task;
import java.net.InetSocketAddress;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
public class FloodgateAuthTask extends FloodgateManagement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
public FloodgateAuthTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player, FloodgatePlayer floodgatePlayer) {
super(core, player, floodgatePlayer);
}
@Override
protected void startLogin() {
BukkitLoginSession session = new BukkitLoginSession(player.getName(), isRegistered, profile);
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
session.setVerified(autoLoginFloodgate.equals("true")
|| (autoLoginFloodgate.equals("linked") && isLinked));
// run login task
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, session);
Bukkit.getScheduler().runTaskAsynchronously(core.getPlugin(), forceLoginTask);
}
protected String getName(Player player) {
return player.getName();
}
protected UUID getUUID(Player player) {
return player.getUniqueId();
}
protected InetSocketAddress getAddress(Player player) {
return player.getAddress();
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.task;
import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
@@ -9,10 +34,10 @@ import com.github.games647.fastlogin.core.message.SuccessMessage;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
import java.util.concurrent.ExecutionException;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -20,22 +45,23 @@ import org.bukkit.metadata.FixedMetadataValue;
public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender, BukkitLoginSession, FastLoginBukkit> {
public ForceLoginTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player) {
super(core, player, getSession(core.getPlugin(), player));
}
private static BukkitLoginSession getSession(FastLoginBukkit plugin, Player player) {
//remove the bungeecord identifier if there is ones
String id = '/' + player.getAddress().getAddress().getHostAddress() + ':' + player.getAddress().getPort();
return plugin.getLoginSessions().remove(id);
public ForceLoginTask(FastLoginCore<Player, CommandSender, FastLoginBukkit> core, Player player,
BukkitLoginSession session) {
super(core, player, session);
}
@Override
public void run() {
//blacklist this target player for BungeeCord ID brute force attacks
// block this target player for BungeeCord ID brute force attacks
FastLoginBukkit plugin = core.getPlugin();
player.setMetadata(core.getPlugin().getName(), new FixedMetadataValue(plugin, true));
if (session != null && !session.getUsername().equals(player.getName())) {
String playerName = player.getName();
plugin.getLog().warn("Player username {} is not matching session {}", playerName, session.getUsername());
return;
}
super.run();
PremiumStatus status = PremiumStatus.CRACKED;
@@ -55,8 +81,8 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
@Override
public void onForceActionSuccess(LoginSession session) {
if (core.getPlugin().isBungeeEnabled()) {
core.getPlugin().sendPluginMessage(player, new SuccessMessage());
if (core.getPlugin().getBungeeManager().isEnabled()) {
core.getPlugin().getBungeeManager().sendPluginMessage(player, new SuccessMessage());
}
}
@@ -78,10 +104,6 @@ public class ForceLoginTask extends ForceLoginManagement<Player, CommandSender,
@Override
public boolean isOnlineMode() {
if (session == null) {
return false;
}
return session.isVerified() && player.getName().equals(session.getUsername());
return session.isVerified();
}
}

View File

@@ -18,10 +18,13 @@ softdepend:
# We depend either ProtocolLib or ProtocolSupport
- ProtocolSupport
- ProtocolLib
# Premium variable
- PlaceholderAPI
- floodgate
# Auth plugins
- AuthMe
- LoginSecurity
- SodionAuth
- xAuth
- LogIt
- UltraAuth
@@ -35,7 +38,7 @@ commands:
permission: ${project.artifactId}.command.premium
cracked:
description: 'Label the invoker or the player specified as cracked if he was marked premium before'
description: 'Label the invoker or the player specified as cracked if marked premium before'
aliases: [unpremium]
usage: /<command> [player]
permission: ${project.artifactId}.command.cracked

View File

@@ -1,42 +0,0 @@
package com.github.games647.fastlogin.bukkit;
import java.security.SecureRandom;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
public class EncryptionUtilTest {
@Test
public void testVerifyToken() throws Exception {
SecureRandom random = new SecureRandom();
byte[] token = EncryptionUtil.generateVerifyToken(random);
assertThat(token, notNullValue());
assertThat(token.length, is(4));
}
// @Test
// public void testDecryptSharedSecret() throws Exception {
//
// }
//
// @Test
// public void testDecryptData() throws Exception {
//
// }
// private static SecretKey createNewSharedKey() {
// try {
// KeyGenerator keygenerator = KeyGenerator.getInstance("AES");
// keygenerator.init(128);
// return keygenerator.generateKey();
// } catch (NoSuchAlgorithmException nosuchalgorithmexception) {
// throw new Error(nosuchalgorithmexception);
// }
// }
}

View File

@@ -0,0 +1,66 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bukkit.listener.protocollib;
import java.security.SecureRandom;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
public class EncryptionUtilTest {
@Test
public void testVerifyToken() throws Exception {
SecureRandom random = new SecureRandom();
byte[] token = EncryptionUtil.generateVerifyToken(random);
assertThat(token, notNullValue());
assertThat(token.length, is(4));
}
// @Test
// public void testDecryptSharedSecret() throws Exception {
//
// }
//
// @Test
// public void testDecryptData() throws Exception {
//
// }
// private static SecretKey createNewSharedKey() {
// try {
// KeyGenerator keygenerator = KeyGenerator.getInstance("AES");
// keygenerator.init(128);
// return keygenerator.generateKey();
// } catch (NoSuchAlgorithmException nosuchalgorithmexception) {
// throw new Error(nosuchalgorithmexception);
// }
// }
}

View File

@@ -1,3 +1,30 @@
<!--
SPDX-License-Identifier: MIT
The MIT License (MIT)
Copyright (c) 2015-2021 <Your name and contributors>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -21,7 +48,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<version>3.2.4</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>false</shadedArtifactAttached>
@@ -60,6 +87,24 @@
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
</repository>
<repository>
<id>nukkitx-repo</id>
<url>https://repo.nukkitx.com/maven-snapshots/</url>
</repository>
<repository>
<id>spigotplugins-repo</id>
<url>https://maven.gamestrike.de/mvn/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
@@ -74,7 +119,25 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>1.14-SNAPSHOT</version>
<version>1.16-R0.5-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Bedrock player bridge -->
<!-- Should be removed one Floodgate 2.0 gets a stable release -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>floodgate-bungee</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Bedrock player bridge -->
<!-- Version 2.0 -->
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@@ -86,5 +149,32 @@
<scope>system</scope>
<systemPath>${project.basedir}/lib/BungeeAuth-1.4.jar</systemPath>
</dependency>
<dependency>
<groupId>de.xxschrandxx.bca</groupId>
<artifactId>BungeeCordAuthenticator</artifactId>
<version>0.0.2</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Bungee</artifactId>
<version>2bdfdc854b</version>
<exclusions>
<exclusion>
<groupId>com.github.Mohist-Community.SodionAuth</groupId>
<artifactId>SodionAuth-Libs</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.core.StoredProfile;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.core.shared.LoginSource;
@@ -21,7 +46,7 @@ public class BungeeLoginSource implements LoginSource {
}
@Override
public void setOnlineMode() {
public void enableOnlinemode() {
connection.setOnlineMode(true);
}
@@ -29,10 +54,11 @@ public class BungeeLoginSource implements LoginSource {
public void kick(String message) {
preLoginEvent.setCancelled(true);
if (message != null)
preLoginEvent.setCancelReason(TextComponent.fromLegacyText(message));
else
if (message == null) {
preLoginEvent.setCancelReason(new ComponentBuilder("Kicked").color(ChatColor.WHITE).create());
} else {
preLoginEvent.setCancelReason(TextComponent.fromLegacyText(message));
}
}
@Override

View File

@@ -1,10 +1,38 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook;
import com.github.games647.fastlogin.bungee.hook.BungeeCordAuthenticatorBungeeHook;
import com.github.games647.fastlogin.bungee.hook.SodionAuthHook;
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.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey;
@@ -17,6 +45,8 @@ import com.google.common.io.ByteStreams;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadFactory;
@@ -26,6 +56,7 @@ import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
import org.slf4j.Logger;
@@ -53,8 +84,12 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
}
//events
getProxy().getPluginManager().registerListener(this, new ConnectListener(this));
getProxy().getPluginManager().registerListener(this, new PluginMessageListener(this));
PluginManager pluginManager = getProxy().getPluginManager();
ConnectListener connectListener = new ConnectListener(this, core.getRateLimiter());
pluginManager.registerListener(this, connectListener);
pluginManager.registerListener(this, new PluginMessageListener(this));
//this is required to listen to incoming messages from the server
getProxy().registerChannel(NamespaceKey.getCombined(getName(), ChangePremiumMessage.CHANGE_CHANNEL));
@@ -79,10 +114,24 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
}
private void registerHook() {
Plugin plugin = getProxy().getPluginManager().getPlugin("BungeeAuth");
if (plugin != null) {
core.setAuthPluginHook(new BungeeAuthHook());
logger.info("Hooked into BungeeAuth");
try {
List<Class<? extends AuthPlugin<ProxiedPlayer>>> hooks = Arrays.asList(
BungeeAuthHook.class, BungeeCordAuthenticatorBungeeHook.class, SodionAuthHook.class);
for (Class<? extends AuthPlugin<ProxiedPlayer>> clazz : hooks) {
String pluginName = clazz.getSimpleName();
pluginName = pluginName.substring(0, pluginName.length() - "Hook".length());
//uses only member classes which uses AuthPlugin interface (skip interfaces)
Plugin plugin = getProxy().getPluginManager().getPlugin(pluginName);
if (plugin != null) {
logger.info("Hooking into auth plugin: {}", pluginName);
core.setAuthPluginHook(
clazz.getDeclaredConstructor(FastLoginBungee.class).newInstance(this));
break;
}
}
} catch (ReflectiveOperationException ex) {
logger.error("Couldn't load the auth hook class", ex);
}
}
@@ -131,4 +180,9 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
public AsyncScheduler getScheduler() {
return scheduler;
}
@Override
public boolean isPluginInstalled(String name) {
return getProxy().getPluginManager().getPlugin(name) != null;
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.event;
import com.github.games647.fastlogin.core.StoredProfile;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.event;
import com.github.games647.fastlogin.core.StoredProfile;

View File

@@ -0,0 +1,51 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.event;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent;
import net.md_5.bungee.api.plugin.Event;
public class BungeeFastLoginPremiumToggleEvent extends Event implements FastLoginPremiumToggleEvent {
private final StoredProfile profile;
private final PremiumToggleReason reason;
public BungeeFastLoginPremiumToggleEvent(StoredProfile profile, PremiumToggleReason reason) {
this.profile = profile;
this.reason = reason;
}
@Override
public StoredProfile getProfile() {
return profile;
}
@Override
public FastLoginPremiumToggleEvent.PremiumToggleReason getReason() {
return reason;
}
}

View File

@@ -1,5 +1,31 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.hook;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import me.vik1395.BungeeAuth.Main;
@@ -18,6 +44,9 @@ public class BungeeAuthHook implements AuthPlugin<ProxiedPlayer> {
private final RequestHandler requestHandler = new RequestHandler();
public BungeeAuthHook(FastLoginBungee plugin) {
}
@Override
public boolean forceLogin(ProxiedPlayer player) {
String playerName = player.getName();

View File

@@ -0,0 +1,93 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.hook;
import java.sql.SQLException;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import de.xxschrandxx.bca.bungee.BungeeCordAuthenticatorBungee;
import de.xxschrandxx.bca.bungee.api.BungeeCordAuthenticatorBungeeAPI;
import net.md_5.bungee.api.connection.ProxiedPlayer;
/**
* GitHub:
* https://github.com/xXSchrandXx/SpigotPlugins/tree/master/BungeeCordAuthenticator
*
* Project page:
*
* Spigot: https://www.spigotmc.org/resources/bungeecordauthenticator.87669/
*/
public class BungeeCordAuthenticatorBungeeHook implements AuthPlugin<ProxiedPlayer> {
public final BungeeCordAuthenticatorBungeeAPI api;
public BungeeCordAuthenticatorBungeeHook(FastLoginBungee plugin) {
api = ((BungeeCordAuthenticatorBungee) plugin.getProxy().getPluginManager()
.getPlugin("BungeeCordAuthenticatorBungee")).getAPI();
plugin.getLog().info("BungeeCordAuthenticatorHook | Hooked successful!");
}
@Override
public boolean forceLogin(ProxiedPlayer player) {
if (api.isAuthenticated(player)) {
return true;
} else {
try {
api.setAuthenticated(player);
}
catch (SQLException e) {
e.printStackTrace();
return false;
}
return true;
}
}
@Override
public boolean isRegistered(String playerName) {
try {
return api.getSQL().checkPlayerEntry(playerName);
}
catch (SQLException e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean forceRegister(ProxiedPlayer player, String password) {
try {
return api.createPlayerEntry(player, password);
}
catch (SQLException e) {
e.printStackTrace();
return false;
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.hook;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import red.mohist.sodionauth.bungee.implementation.BungeePlayer;
import red.mohist.sodionauth.core.SodionAuthApi;
import red.mohist.sodionauth.core.exception.AuthenticatedException;
/**
* GitHub: https://github.com/Mohist-Community/SodionAuth
* <p>
* Project page: https://gitea.e-loli.com/SodionAuth/SodionAuth
* <p>
* Bukkit: Unknown
* <p>
* Spigot: https://www.spigotmc.org/resources/sodionauth.76944/
*/
public class SodionAuthHook implements AuthPlugin<ProxiedPlayer> {
private final FastLoginBungee plugin;
public SodionAuthHook(FastLoginBungee plugin) {
this.plugin = plugin;
}
@Override
public boolean forceLogin(ProxiedPlayer player) {
try {
SodionAuthApi.login(new BungeePlayer(player));
} catch (AuthenticatedException e) {
plugin.getLog().warn(ALREADY_AUTHENTICATED, player);
return false;
}
return true;
}
@Override
public boolean forceRegister(ProxiedPlayer player, String password) {
try{
return SodionAuthApi.register(new BungeePlayer(player), password);
} catch (UnsupportedOperationException e){
plugin.getLog().warn("Currently SodionAuth is not accepting forceRegister, " +
"It may be caused by unsupported AuthBackend");
return false;
}
}
@Override
public boolean isRegistered(String playerName) {
return SodionAuthApi.isRegistered(playerName);
}
}

View File

@@ -1,12 +1,44 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.listener;
import com.github.games647.craftapi.UUIDAdapter;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.task.AsyncPremiumCheck;
import com.github.games647.fastlogin.bungee.task.FloodgateAuthTask;
import com.github.games647.fastlogin.bungee.task.ForceLoginTask;
import com.github.games647.fastlogin.core.RateLimiter;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.google.common.base.Throwables;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Field;
import java.util.UUID;
@@ -24,29 +56,69 @@ import net.md_5.bungee.connection.LoginResult.Property;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Enables online mode logins for specified users and sends plugin message to the Bukkit version of this plugin in
* order to clear that the connection is online mode.
*/
public class ConnectListener implements Listener {
private static final String UUID_FIELD_NAME = "uniqueId";
private static final MethodHandle uniqueIdSetter;
static {
MethodHandle setHandle = null;
try {
Lookup lookup = MethodHandles.lookup();
Class.forName("net.md_5.bungee.connection.InitialHandler");
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
uuidField.setAccessible(true);
setHandle = lookup.unreflectSetter(uuidField);
} catch (ClassNotFoundException classNotFoundException) {
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
logger.error(
"Cannot find Bungee initial handler; Disabling premium UUID and skin won't work.",
classNotFoundException
);
} catch (ReflectiveOperationException reflectiveOperationException) {
reflectiveOperationException.printStackTrace();
}
uniqueIdSetter = setHandle;
}
private final FastLoginBungee plugin;
private final RateLimiter rateLimiter;
private final Property[] emptyProperties = {};
public ConnectListener(FastLoginBungee plugin) {
public ConnectListener(FastLoginBungee plugin, RateLimiter rateLimiter) {
this.plugin = plugin;
this.rateLimiter = rateLimiter;
}
@EventHandler
public void onPreLogin(PreLoginEvent preLoginEvent) {
PendingConnection connection = preLoginEvent.getConnection();
if (preLoginEvent.isCancelled()) {
return;
}
preLoginEvent.registerIntent(plugin);
if (!rateLimiter.tryAcquire()) {
plugin.getLog().warn("Simple Anti-Bot join limit - Ignoring {}", connection);
return;
}
PendingConnection connection = preLoginEvent.getConnection();
Runnable asyncPremiumCheck = new AsyncPremiumCheck(plugin, preLoginEvent, connection);
String username = connection.getName();
plugin.getLog().info("Incoming login request for {} from {}", username, connection.getSocketAddress());
preLoginEvent.registerIntent(plugin);
Runnable asyncPremiumCheck = new AsyncPremiumCheck(plugin, preLoginEvent, connection, username);
plugin.getScheduler().runAsync(asyncPremiumCheck);
}
@@ -59,47 +131,77 @@ public class ConnectListener implements Listener {
//use the login event instead of the post login event in order to send the login success packet to the client
//with the offline uuid this makes it possible to set the skin then
PendingConnection connection = loginEvent.getConnection();
InitialHandler initialHandler = (InitialHandler) connection;
String username = initialHandler.getLoginRequest().getData();
if (connection.isOnlineMode()) {
LoginSession session = plugin.getSession().get(connection);
session.setUuid(connection.getUniqueId());
UUID verifiedUUID = connection.getUniqueId();
String verifiedUsername = connection.getName();
session.setUuid(verifiedUUID);
session.setVerifiedUsername(verifiedUsername);
StoredProfile playerProfile = session.getProfile();
playerProfile.setId(connection.getUniqueId());
playerProfile.setId(verifiedUUID);
//bungeecord will do this automatically so override it on disabled option
if (!plugin.getCore().getConfig().get("premiumUuid", true)) {
try {
UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
// bungeecord will do this automatically so override it on disabled option
if (uniqueIdSetter != null) {
InitialHandler initialHandler = (InitialHandler) connection;
//bungeecord doesn't support overriding the premium uuid
//so we have to do it with reflection
Field idField = InitialHandler.class.getDeclaredField("uniqueId");
idField.setAccessible(true);
idField.set(connection, offlineUUID);
} catch (NoSuchFieldException | IllegalAccessException ex) {
plugin.getLog().error("Failed to set offline uuid of {}", username, ex);
if (!plugin.getCore().getConfig().get("premiumUuid", true)) {
setOfflineId(initialHandler, verifiedUsername);
}
}
if (!plugin.getCore().getConfig().get("forwardSkin", true)) {
//this is null on offline mode
LoginResult loginProfile = initialHandler.getLoginProfile();
if (loginProfile != null) {
if (!plugin.getCore().getConfig().get("forwardSkin", true)) {
// this is null on offline mode
LoginResult loginProfile = initialHandler.getLoginProfile();
loginProfile.setProperties(emptyProperties);
}
}
}
}
private void setOfflineId(InitialHandler connection, String username) {
try {
final UUID oldPremiumId = connection.getUniqueId();
final UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
// BungeeCord only allows setting the UUID in PreLogin events and before requesting online mode
// However if online mode is requested, it will override previous values
// So we have to do it with reflection
uniqueIdSetter.invokeExact(connection, offlineUUID);
String format = "Overridden UUID from {} to {} (based of {}) on {}";
plugin.getLog().info(format, oldPremiumId, offlineUUID, username, connection);
} catch (Exception ex) {
plugin.getLog().error("Failed to set offline uuid of {}", username, ex);
} catch (Throwable throwable) {
// throw remaining exceptions like outofmemory that we shouldn't handle ourself
Throwables.throwIfUnchecked(throwable);
}
}
@EventHandler
public void onServerConnected(ServerConnectedEvent serverConnectedEvent) {
ProxiedPlayer player = serverConnectedEvent.getPlayer();
Server server = serverConnectedEvent.getServer();
Runnable loginTask = new ForceLoginTask(plugin.getCore(), player, server);
if (plugin.isPluginInstalled("floodgate")) {
FloodgatePlayer floodgatePlayer = FloodgateApi.getInstance().getPlayer(player.getUniqueId());
if (floodgatePlayer != null) {
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer, server);
plugin.getScheduler().runAsync(floodgateAuthTask);
return;
}
}
BungeeLoginSession session = plugin.getSession().get(player.getPendingConnection());
if (session == null) {
return;
}
// 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);
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.listener;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.task;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
@@ -12,7 +37,6 @@ import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PreLoginEvent;
import net.md_5.bungee.connection.InitialHandler;
public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSender, BungeeLoginSource>
implements Runnable {
@@ -20,22 +44,23 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
private final FastLoginBungee plugin;
private final PreLoginEvent preLoginEvent;
private final String username;
private final PendingConnection connection;
public AsyncPremiumCheck(FastLoginBungee plugin, PreLoginEvent preLoginEvent, PendingConnection connection) {
public AsyncPremiumCheck(FastLoginBungee plugin, PreLoginEvent preLoginEvent, PendingConnection connection,
String username) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
this.plugin = plugin;
this.preLoginEvent = preLoginEvent;
this.connection = connection;
this.username = username;
}
@Override
public void run() {
plugin.getSession().remove(connection);
InitialHandler initialHandler = (InitialHandler) connection;
String username = initialHandler.getLoginRequest().getData();
try {
super.onLogin(username, new BungeeLoginSource(connection, preLoginEvent));
} finally {
@@ -53,7 +78,7 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
@Override
public void requestPremiumLogin(BungeeLoginSource source, StoredProfile profile,
String username, boolean registered) {
source.setOnlineMode();
source.enableOnlinemode();
plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile));
String ip = source.getAddress().getAddress().getHostAddress();

View File

@@ -1,9 +1,36 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.task;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.event.BungeeFastLoginPremiumToggleEvent;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.event.FastLoginPremiumToggleEvent.PremiumToggleReason;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
@@ -46,6 +73,10 @@ public class AsyncToggleMessage implements Runnable {
playerProfile.setPremium(false);
playerProfile.setId(null);
core.getStorage().save(playerProfile);
PremiumToggleReason reason = (!isPlayerSender || !sender.getName().equalsIgnoreCase(playerProfile.getName())) ?
PremiumToggleReason.COMMAND_OTHER : PremiumToggleReason.COMMAND_SELF;
core.getPlugin().getProxy().getPluginManager().callEvent(
new BungeeFastLoginPremiumToggleEvent(playerProfile, reason));
sendMessage("remove-premium");
}
@@ -58,6 +89,10 @@ public class AsyncToggleMessage implements Runnable {
playerProfile.setPremium(true);
core.getStorage().save(playerProfile);
PremiumToggleReason reason = (!isPlayerSender || !sender.getName().equalsIgnoreCase(playerProfile.getName())) ?
PremiumToggleReason.COMMAND_OTHER : PremiumToggleReason.COMMAND_SELF;
core.getPlugin().getProxy().getPluginManager().callEvent(
new BungeeFastLoginPremiumToggleEvent(playerProfile, reason));
sendMessage("add-premium");
}

View File

@@ -0,0 +1,82 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.task;
import java.net.InetSocketAddress;
import java.util.UUID;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.FloodgateManagement;
public class FloodgateAuthTask
extends FloodgateManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
private final Server server;
public FloodgateAuthTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core, ProxiedPlayer player,
FloodgatePlayer floodgatePlayer, Server server) {
super(core, player, floodgatePlayer);
this.server = server;
}
@Override
protected void startLogin() {
BungeeLoginSession session = new BungeeLoginSession(player.getName(), isRegistered, profile);
// enable auto login based on the value of 'autoLoginFloodgate' in config.yml
boolean forcedOnlineMode = autoLoginFloodgate.equals("true")
|| (autoLoginFloodgate.equals("linked") && isLinked);
// run login task
Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, server, session,
forcedOnlineMode);
core.getPlugin().getScheduler().runAsync(forceLoginTask);
}
@Override
protected String getName(ProxiedPlayer player) {
return player.getName();
}
@Override
protected UUID getUUID(ProxiedPlayer player) {
return player.getUniqueId();
}
@Override
protected InetSocketAddress getAddress(ProxiedPlayer player) {
return player.getAddress();
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.bungee.task;
import com.github.games647.fastlogin.bungee.BungeeLoginSession;
@@ -10,10 +35,10 @@ import com.github.games647.fastlogin.core.message.LoginActionMessage.Type;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.ForceLoginManagement;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
import java.util.UUID;
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@@ -24,11 +49,21 @@ public class ForceLoginTask
private final Server server;
//treat player as if they had a premium account, even when they don't
//used for Floodgate auto login/register
private final boolean forcedOnlineMode;
public ForceLoginTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core,
ProxiedPlayer player, Server server) {
super(core, player, core.getPlugin().getSession().get(player.getPendingConnection()));
ProxiedPlayer player, Server server, BungeeLoginSession session, boolean forcedOnlineMode) {
super(core, player, session);
this.server = server;
this.forcedOnlineMode = forcedOnlineMode;
}
public ForceLoginTask(FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core, ProxiedPlayer player,
Server server, BungeeLoginSession session) {
this(core, player, server, session, false);
}
@Override
@@ -91,6 +126,6 @@ public class ForceLoginTask
@Override
public boolean isOnlineMode() {
return player.getPendingConnection().isOnlineMode();
return forcedOnlineMode || player.getPendingConnection().isOnlineMode();
}
}

View File

@@ -11,6 +11,8 @@ author: games647, https://github.com/games647/FastLogin/graphs/contributors
softDepends:
# BungeeCord auth plugins
- BungeeAuth
- BungeeCordAuthenticatorBungee
- SodionAuth
description: |
${project.description}

View File

@@ -1,3 +1,30 @@
<!--
SPDX-License-Identifier: MIT
The MIT License (MIT)
Copyright (c) 2015-2021 <Your name and contributors>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -26,6 +53,11 @@
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
</repository>
<!-- Floodgate -->
<repository>
<id>nukkitx-snapshot</id>
<url>https://repo.nukkitx.com/maven-snapshots/</url>
</repository>
</repositories>
<dependencies>
@@ -35,14 +67,14 @@
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.2</version>
<version>4.0.3</version>
</dependency>
<!--Logging framework implements slf4j which is required by hikari-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.30</version>
<version>1.7.32</version>
</dependency>
<!-- snakeyaml is present in Bungee, Spigot, Cauldron and so we could use this independent implementation -->
@@ -58,6 +90,14 @@
</exclusions>
</dependency>
<!--Floodgate for Xbox Live Authentication-->
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Common component for contacting the Mojang API-->
<dependency>
<groupId>com.github.games647</groupId>

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core;
import com.google.common.util.concurrent.MoreExecutors;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core;
import com.github.games647.craftapi.UUIDAdapter;
@@ -12,7 +37,6 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant;
import java.util.Optional;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.ThreadFactory;
@@ -38,11 +62,6 @@ public class AuthStorage {
this.core = core;
config.setPoolName(core.getPlugin().getName());
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
Properties properties = new Properties();
properties.setProperty("date_string_format", "yyyy-MM-dd HH:mm:ss");
properties.setProperty("useSSL", String.valueOf(useSSL));
config.setDataSourceProperties(properties);
ThreadFactory platformThreadFactory = core.getPlugin().getThreadFactory();
if (platformThreadFactory != null) {
config.setThreadFactory(platformThreadFactory);
@@ -56,15 +75,57 @@ public class AuthStorage {
jdbcUrl += "sqlite://" + databasePath;
config.setConnectionTestQuery("SELECT 1");
config.setMaximumPoolSize(1);
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
// format strings retrieved by the timestamp column to match them from MySQL
config.addDataSourceProperty("date_string_format", "yyyy-MM-dd HH:mm:ss");
// TODO: test first for compatibility
// config.addDataSourceProperty("date_precision", "seconds");
} else {
jdbcUrl += "mysql://" + host + ':' + port + '/' + databasePath;
// Require SSL on the server if requested in config - this will also verify certificate
// Those values are deprecated in favor of sslMode
config.addDataSourceProperty("useSSL", useSSL);
config.addDataSourceProperty("requireSSL", useSSL);
// prefer encrypted if possible
config.addDataSourceProperty("sslMode", "PREFERRED");
// adding paranoid hides hostname, username, version and so
// could be useful for hiding server details
config.addDataSourceProperty("paranoid", true);
// enable MySQL specific optimizations
// default prepStmtCacheSize 25 - amount of cached statements - enough for us
// default prepStmtCacheSqlLimit 256 - length of SQL - our queries are not longer
// disabled by default - will return the same prepared statement instance
config.addDataSourceProperty("cachePrepStmts", true);
// default prepStmtCacheSize 25 - amount of cached statements
config.addDataSourceProperty("prepStmtCacheSize", 250);
// default prepStmtCacheSqlLimit 256 - length of SQL
config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
// default false - available in newer versions caches the statements server-side
config.addDataSourceProperty("useServerPrepStmts", true);
// default false - prefer use of local values for autocommit and
// transaction isolation (alwaysSendSetIsolation) should only be enabled if always use the set* methods
// instead of raw SQL
// https://forums.mysql.com/read.php?39,626495,626512
config.addDataSourceProperty("useLocalSessionState", true);
// rewrite batched statements to a single statement, adding them behind each other
// only useful for addBatch statements and inserts
config.addDataSourceProperty("rewriteBatchedStatements", true);
// cache result metadata
config.addDataSourceProperty("cacheResultSetMetadata", true);
// cache results of show variables and collation per URL
config.addDataSourceProperty("cacheServerConfiguration", true);
// default false - set auto commit only if not matching
config.addDataSourceProperty("elideSetAutoCommits", true);
// default true - internal timers for idle calculation -> removes System.getCurrentTimeMillis call per query
// Some platforms are slow on this and it could affect the throughput about 3% according to MySQL
// performance gems presentation
// In our case it can be useful to see the time in error messages
// config.addDataSourceProperty("maintainTimeStats", false);
}
config.setJdbcUrl(jdbcUrl);
@@ -148,31 +209,36 @@ public class AuthStorage {
try (Connection con = dataSource.getConnection()) {
String uuid = playerProfile.getOptId().map(UUIDAdapter::toMojangId).orElse(null);
if (playerProfile.isSaved()) {
try (PreparedStatement saveStmt = con.prepareStatement(UPDATE_PROFILE)) {
saveStmt.setString(1, uuid);
saveStmt.setString(2, playerProfile.getName());
saveStmt.setBoolean(3, playerProfile.isPremium());
saveStmt.setString(4, playerProfile.getLastIp());
playerProfile.getSaveLock().lock();
try {
if (playerProfile.isSaved()) {
try (PreparedStatement saveStmt = con.prepareStatement(UPDATE_PROFILE)) {
saveStmt.setString(1, uuid);
saveStmt.setString(2, playerProfile.getName());
saveStmt.setBoolean(3, playerProfile.isPremium());
saveStmt.setString(4, playerProfile.getLastIp());
saveStmt.setLong(5, playerProfile.getRowId());
saveStmt.execute();
}
} else {
try (PreparedStatement saveStmt = con.prepareStatement(INSERT_PROFILE, RETURN_GENERATED_KEYS)) {
saveStmt.setString(1, uuid);
saveStmt.setLong(5, playerProfile.getRowId());
saveStmt.execute();
}
} else {
try (PreparedStatement saveStmt = con.prepareStatement(INSERT_PROFILE, RETURN_GENERATED_KEYS)) {
saveStmt.setString(1, uuid);
saveStmt.setString(2, playerProfile.getName());
saveStmt.setBoolean(3, playerProfile.isPremium());
saveStmt.setString(4, playerProfile.getLastIp());
saveStmt.setString(2, playerProfile.getName());
saveStmt.setBoolean(3, playerProfile.isPremium());
saveStmt.setString(4, playerProfile.getLastIp());
saveStmt.execute();
try (ResultSet generatedKeys = saveStmt.getGeneratedKeys()) {
if (generatedKeys != null && generatedKeys.next()) {
playerProfile.setRowId(generatedKeys.getInt(1));
saveStmt.execute();
try (ResultSet generatedKeys = saveStmt.getGeneratedKeys()) {
if (generatedKeys.next()) {
playerProfile.setRowId(generatedKeys.getInt(1));
}
}
}
}
} finally {
playerProfile.getSaveLock().unlock();
}
} catch (SQLException ex) {
core.getPlugin().getLog().error("Failed to save playerProfile {}", playerProfile, ex);

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core;
import com.github.games647.craftapi.cache.SafeCacheBuilder;

View File

@@ -1,10 +1,45 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core;
public enum PremiumStatus {
PREMIUM,
PREMIUM("Premium"),
CRACKED,
CRACKED("Cracked"),
UNKNOWN
UNKNOWN("Unknown");
private final String readableName;
PremiumStatus(String readableName) {
this.readableName = readableName;
}
public String getReadableName() {
return readableName;
}
}

View File

@@ -0,0 +1,66 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name 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;
/**
* Limit the number of requests with a maximum size. Each requests expires after the specified time making it available
* for another request.
*/
public class RateLimiter {
private final long[] requests;
private final long expireTime;
private int position;
public RateLimiter(int maxLimit, long expireTime) {
this.requests = new long[maxLimit];
this.expireTime = expireTime;
}
/**
* Ask if access is allowed. If so register the request.
*
* @return true if allowed - false otherwise without any side effects
*/
public boolean tryAcquire() {
// current time millis is not monotonic - it can jump back depending on user choice or NTP
long now = System.nanoTime() / 1_000_000;
// after this the request should be expired
long toBeExpired = now - expireTime;
synchronized (this) {
// having synchronized will limit the amount of concurrency a lot
long oldest = requests[position];
if (oldest < toBeExpired) {
requests[position] = now;
position = (position + 1) % requests.length;
return true;
}
return false;
}
}
}

View File

@@ -1,14 +1,42 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core;
import com.github.games647.craftapi.model.Profile;
import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;
public class StoredProfile extends Profile {
private long rowId;
private final ReentrantLock saveLock = new ReentrantLock();
private boolean premium;
private String lastIp;
@@ -27,6 +55,10 @@ public class StoredProfile extends Profile {
this(-1, uuid, playerName, premium, lastIp, Instant.now());
}
public ReentrantLock getSaveLock() {
return saveLock;
}
public synchronized boolean isSaved() {
return rowId >= 0;
}
@@ -80,6 +112,21 @@ public class StoredProfile extends Profile {
this.lastLogin = lastLogin;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof StoredProfile)) return false;
if (!super.equals(o)) return false;
StoredProfile that = (StoredProfile) o;
return rowId == that.rowId && premium == that.premium
&& Objects.equals(lastIp, that.lastIp) && lastLogin.equals(that.lastLogin);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), rowId, premium, lastIp, lastLogin);
}
@Override
public synchronized String toString() {
return this.getClass().getSimpleName() + '{' +

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.hooks;
/**
@@ -8,6 +33,8 @@ package com.github.games647.fastlogin.core.hooks;
*/
public interface AuthPlugin<P> {
String ALREADY_AUTHENTICATED = "Player {} is already authenticated. Cancelling force login.";
/**
* Login the premium (paid account) player after the player joined successfully the server.
*

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.hooks;
import java.security.SecureRandom;

View File

@@ -0,0 +1,112 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.hooks;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
import java.io.IOException;
import java.util.Optional;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
public class FloodgateHook<P extends C, C, S extends LoginSource> {
private final FastLoginCore<P, C, ?> core;
public FloodgateHook(FastLoginCore<P, C, ?> core) {
this.core = core;
}
/**
* Check if the player's name conflicts an existing Java player's name, and
* kick them if it does
*
* @param username the name of the player
* @param source an instance of LoginSource
*/
public void checkFloodgateNameConflict(String username, LoginSource source, FloodgatePlayer floodgatePlayer) {
String allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
// check if the Bedrock player is linked to a Java account
boolean isLinked = ((FloodgatePlayer) floodgatePlayer).getLinkedPlayer() != null;
if (allowConflict.equals("false")
|| allowConflict.equals("linked") && !isLinked) {
// check for conflicting Premium Java name
Optional<Profile> premiumUUID = Optional.empty();
try {
premiumUUID = core.getResolver().findProfile(username);
} catch (IOException | RateLimitException e) {
core.getPlugin().getLog().error(
"Could not check wether Floodgate Player {}'s name conflicts a premium Java player's name.",
username);
try {
source.kick("Could not check if your name conflicts an existing premium Java account's name.\n"
+ "This is usually a serverside error.");
} catch (Exception e1) {
core.getPlugin().getLog().error("Could not kick Player {}", username);
}
}
if (premiumUUID.isPresent()) {
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing premium Java account's name",
username);
try {
source.kick("Your name conflicts an existing premium Java account's name");
} catch (Exception e) {
core.getPlugin().getLog().error("Could not kick Player {}", username);
}
}
} else {
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
}
}
/**
* The FloodgateApi does not support querying players by name, so this function
* iterates over every online FloodgatePlayer and checks if the requested
* username can be found
*
* @param username the name of the player
* @return FloodgatePlayer if found, null otherwise
*/
public FloodgatePlayer getFloodgatePlayer(String username) {
if (core.getPlugin().isPluginInstalled("floodgate")) {
for (FloodgatePlayer floodgatePlayer : FloodgateApi.getInstance().getPlayers()) {
if (floodgatePlayer.getUsername().equals(username)) {
return floodgatePlayer;
}
}
}
return null;
}
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.hooks;
@FunctionalInterface

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.message;
import com.google.common.io.ByteArrayDataInput;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.message;
import com.google.common.io.ByteArrayDataInput;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.message;
import com.google.common.io.ByteArrayDataInput;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.message;
public class NamespaceKey {

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.message;
import com.google.common.io.ByteArrayDataInput;

View File

@@ -0,0 +1,25 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

View File

@@ -0,0 +1,25 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

View File

@@ -1,9 +1,35 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.shared;
import com.github.games647.craftapi.resolver.MojangResolver;
import com.github.games647.craftapi.resolver.http.RotatingProxySelector;
import com.github.games647.fastlogin.core.AuthStorage;
import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.RateLimiter;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
@@ -23,6 +49,7 @@ import java.nio.file.Path;
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;
@@ -45,6 +72,8 @@ import static java.util.stream.Collectors.toSet;
*/
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<>();
@@ -54,6 +83,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
private Configuration config;
private AuthStorage storage;
private RateLimiter rateLimiter;
private PasswordGenerator<P> passwordGenerator = new DefaultPasswordGenerator<>();
private AuthPlugin<P> authPlugin;
@@ -81,8 +111,16 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
});
} catch (IOException ioEx) {
plugin.getLog().error("Failed to load yaml files", ioEx);
return;
}
int maxCon = config.getInt("anti-bot.connections", 200);
long expireTime = config.getLong("anti-bot.expire", 5) * 60 * 1_000L;
if (expireTime > MAX_EXPIRE_RATE) {
expireTime = MAX_EXPIRE_RATE;
}
rateLimiter = new RateLimiter(maxCon, expireTime);
Set<Proxy> proxies = config.getStringList("proxies")
.stream()
.map(HostAndPort::fromString)
@@ -119,7 +157,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
config = configProvider.load(reader, defaults);
}
//explicitly add keys here, because Configuration.getKeys doesn't return the keys from the default configuration
// explicitly add keys here, because Configuration.getKeys doesn't return the keys from the default configuration
for (String key : defaults.getKeys()) {
config.set(key, config.get(key));
}
@@ -151,12 +189,13 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
}
public boolean setupDatabase() {
HikariConfig databaseConfig = new HikariConfig();
databaseConfig.setDriverClassName(config.getString("driver"));
if (!checkDriver(databaseConfig.getDriverClassName())) {
if (!checkDriver(config.getString("driver"))) {
return false;
}
HikariConfig databaseConfig = new HikariConfig();
databaseConfig.setDriverClassName(config.getString("driver"));
String host = config.get("host", "");
int port = config.get("port", 3306);
String database = config.getString("database");
@@ -216,6 +255,10 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
return authPlugin;
}
public RateLimiter getRateLimiter() {
return rateLimiter;
}
public void setAuthPluginHook(AuthPlugin<P> authPlugin) {
this.authPlugin = authPlugin;
}
@@ -224,14 +267,12 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
Path dataFolder = plugin.getPluginFolder();
try {
if (Files.notExists(dataFolder)) {
Files.createDirectories(dataFolder);
}
Files.createDirectories(dataFolder);
Path configFile = dataFolder.resolve(fileName);
if (Files.notExists(configFile)) {
try (InputStream defaultStream = getClass().getClassLoader().getResourceAsStream(fileName)) {
Files.copy(defaultStream, configFile);
Files.copy(Objects.requireNonNull(defaultStream), configFile);
}
}
} catch (IOException ioExc) {

View File

@@ -0,0 +1,158 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.shared;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Optional;
import java.util.UUID;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
public abstract class FloodgateManagement<P extends C, C, L extends LoginSession, T extends PlatformPlugin<C>>
implements Runnable {
protected final FastLoginCore<P, C, T> core;
protected final P player;
private final FloodgatePlayer floodgatePlayer;
private final String username;
//config.yml values that might be accessed by multiple methods
protected final String autoLoginFloodgate;
protected final String autoRegisterFloodgate;
protected final String allowNameConflict;
//variables initialized through run() and accesses by subclasss
protected boolean isRegistered;
protected StoredProfile profile;
protected boolean isLinked;
public FloodgateManagement(FastLoginCore<P, C, T> core, P player, FloodgatePlayer floodgatePlayer) {
this.core = core;
this.player = player;
this.floodgatePlayer = floodgatePlayer;
this.username = getName(player);
//load values from config.yml
autoLoginFloodgate = core.getConfig().get("autoLoginFloodgate").toString().toLowerCase();
autoRegisterFloodgate = core.getConfig().get("autoRegisterFloodgate").toString().toLowerCase();
allowNameConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
}
@Override
public void run() {
core.getPlugin().getLog().info("Player {} is connecting through Geyser Floodgate.", username);
// check if the Bedrock player is linked to a Java account
isLinked = floodgatePlayer.getLinkedPlayer() != null;
AuthPlugin<P> authPlugin = core.getAuthPluginHook();
try {
isRegistered = authPlugin.isRegistered(username);
} catch (Exception ex) {
core.getPlugin().getLog().error(
"An error has occured while checking if player {} is registered",
username, ex);
return;
}
//decide if checks should be made for conflicting Java player names
if (isNameCheckRequired()) {
// check for conflicting Premium Java name
Optional<Profile> premiumUUID = Optional.empty();
try {
premiumUUID = core.getResolver().findProfile(username);
} catch (IOException | RateLimitException e) {
core.getPlugin().getLog().error(
"Could not check whether Floodgate Player {}'s name conflicts a premium Java account's name.",
username, e);
return;
}
//stop execution if player's name is conflicting
if (premiumUUID.isPresent()) {
return;
}
}
if (!isRegistered && !isAutoRegisterAllowed()) {
return;
}
//logging in from bedrock for a second time threw an error with UUID
profile = core.getStorage().loadProfile(username);
if (profile == null) {
profile = new StoredProfile(getUUID(player), username, true, getAddress(player).toString());
}
//start Bukkit/Bungee specific tasks
startLogin();
}
/**
* Decude if the player can be auto registered.
* The config option 'non-conflicting' is ignored by this function.
* @return true if the Player can be registered automatically
*/
private boolean isAutoRegisterAllowed() {
return "true".equals(autoRegisterFloodgate)
|| "no-conflict".equals(autoRegisterFloodgate) // this was checked before
|| ("linked".equals(autoRegisterFloodgate) && isLinked);
}
/**
* Decides wether checks for conflicting Java names should be made
* @return ture if an API call to Mojang is needed
*/
private boolean isNameCheckRequired() {
//linked players have the same name as their Java profile
//OR
//if allowNameConflict is 'false' or 'linked' and the player had a conflicting
//name, than they would have been kicked in FloodgateHook#checkNameConflict
if (isLinked || !"true".equals(allowNameConflict)) {
return false;
}
//autoRegisterFloodgate should only be checked if then player is not yet registered
if (!isRegistered && "no-conflict".equals(autoRegisterFloodgate)) {
return true;
}
return "no-conflict".equals(autoLoginFloodgate);
}
protected abstract void startLogin();
protected abstract String getName(P player);
protected abstract UUID getUUID(P player);
protected abstract InetSocketAddress getAddress(P player);
}

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.AuthStorage;
@@ -20,7 +45,13 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
@Override
public void run() {
if (!isOnline(player) || session == null) {
if (!isOnline(player)) {
core.getPlugin().getLog().info("Player {} disconnected", player);
return;
}
if (session == null) {
core.getPlugin().getLog().info("No valid session found for {}", player);
return;
}

View File

@@ -1,31 +1,69 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.shared;
import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.hooks.FloodgateHook;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import java.util.Optional;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import net.md_5.bungee.config.Configuration;
public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
protected final FastLoginCore<P, C, ?> core;
protected final AuthPlugin<P> authHook;
private final FloodgateHook<P, C, ?> floodgateHook;
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook) {
this.core = core;
this.authHook = authHook;
this.floodgateHook = new FloodgateHook<>(core);
}
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 Floodgate
FloodgatePlayer floodgatePlayer = floodgateHook.getFloodgatePlayer(username);
if (floodgatePlayer != null) {
floodgateHook.checkFloodgateNameConflict(username, source, floodgatePlayer);
return;
}
callFastLoginPreLoginEvent(username, source, profile);
Configuration config = core.getConfig();
@@ -35,6 +73,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
try {
if (profile.isSaved()) {
if (profile.isPremium()) {
core.getPlugin().getLog().info("Requesting premium login for registered player: {}", username);
requestPremiumLogin(source, profile, username, true);
} else {
startCrackedSession(source, profile, username);

View File

@@ -1,34 +1,69 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.StoredProfile;
import com.google.common.base.Objects;
import java.util.UUID;
public abstract class LoginSession {
private final String username;
private final StoredProfile profile;
private String requestUsername;
private String username;
private UUID uuid;
protected boolean registered;
public LoginSession(String username, boolean registered, StoredProfile profile) {
this.username = username;
public LoginSession(String requestUsername, boolean registered, StoredProfile profile) {
this.requestUsername = requestUsername;
this.username = requestUsername;
this.registered = registered;
this.profile = profile;
}
public String getRequestUsername() {
return requestUsername;
}
public String getUsername() {
return username;
}
public synchronized void setVerifiedUsername(String username) {
this.username = username;
}
/**
* This value is always false if we authenticate the player with a cracked authentication
*
* @return
* @return This value is always false if we authenticate the player with a cracked authentication
*/
public boolean needsRegistration() {
public synchronized boolean needsRegistration() {
return !registered;
}
@@ -56,11 +91,12 @@ public abstract class LoginSession {
@Override
public synchronized String toString() {
return this.getClass().getSimpleName() + '{' +
"username='" + username + '\'' +
", profile=" + profile +
", uuid=" + uuid +
", registered=" + registered +
'}';
return Objects.toStringHelper(this)
.add("profile", profile)
.add("requestUsername", requestUsername)
.add("username", username)
.add("uuid", uuid)
.add("registered", registered)
.toString();
}
}

View File

@@ -1,10 +1,35 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.shared;
import java.net.InetSocketAddress;
public interface LoginSource {
void setOnlineMode() throws Exception;
void enableOnlinemode() throws Exception;
void kick(String message) throws Exception;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.AsyncScheduler;
@@ -20,6 +45,8 @@ public interface PlatformPlugin<C> {
AsyncScheduler getScheduler();
boolean isPluginInstalled(String name);
default void sendMultiLineMessage(C receiver, String message) {
for (String line : message.split("%nl%")) {
sendMessage(receiver, line);

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name 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.event;
import com.github.games647.fastlogin.core.StoredProfile;

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name 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.event;
public interface FastLoginCancellableEvent {

View File

@@ -1,3 +1,28 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name 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.event;
import com.github.games647.fastlogin.core.StoredProfile;

View File

@@ -0,0 +1,39 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name 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.event;
import com.github.games647.fastlogin.core.StoredProfile;
public interface FastLoginPremiumToggleEvent {
StoredProfile getProfile();
PremiumToggleReason getReason();
enum PremiumToggleReason {
COMMAND_SELF,
COMMAND_OTHER
}
}

View File

@@ -3,7 +3,22 @@
# Source code: https://github.com/games647/FastLogin
#
# You can access the newest config here:
# https://github.com/games647/FastLogin/blob/master/core/src/main/resources/config.yml
# https://github.com/games647/FastLogin/blob/main/core/src/main/resources/config.yml
# This a **very** simple anti bot protection. Recommendation is to use a a dedicated program to approach this
# problem. Low level firewalls like uwf (or iptables direct) are more efficient than a Minecraft plugin. TCP reverse
# proxies could also be used and offload some work even to different host.
#
# The settings wil limit how many connections this plugin will handle. After hitting this limit. FastLogin will
# completely ignore incoming connections. Effectively there will be no database requests and network requests.
# Therefore auto logins won't be possible.
anti-bot:
# Image the following like bucket. The following is total amount that is allowed in this bucket, while expire
# means how long it takes for every entry to expire.
# Total number of connections
connections: 600
# Amount of minutes after the first connection got inserted will expire and made available
expire: 10
# Request a premium login without forcing the player to type a command
#
@@ -21,6 +36,15 @@
# For more information: https://github.com/games647/FastLogin#why-do-players-have-to-invoke-a-command
autoRegister: false
# Should FastLogin respect per IP limit of registrations (e.g. in AuthMe)
# Because most auth plugins do their stuff async - FastLogin will still think the player was registered
# To work best - you also need to enable auto-register-unknown
#
# If set to true - FastLogin will always attempt to register the player, even if the limit is exceeded
# It is up to the auth plugin to handle the excessive registration
# https://github.com/games647/FastLogin/issues/458
respectIpLimit: false
# This is extra configuration option to the feature above. If we request a premium authentication from a player who
# isn't actual premium but used a premium username, the player will disconnect with the reason "invalid session" or
# "bad login".
@@ -32,7 +56,8 @@ secondAttemptCracked: false
# New cracked players will be kicked from server. Good if you want switch from offline-mode to online-mode without
# losing players!
#
# Existing cracked and premium players could still join your server. Moreover you could add playernames to a whitelist.
# Existing cracked and premium players could still join your server. Moreover you could add playernames to a
# allowlist.
# So that these cracked players could join too although they are new players.
switchMode: false
@@ -60,14 +85,15 @@ premiumUuid: false
# player changed it's username and we just update the name in the database.
# Examples:
# #### Case 1
# nameChangeCheck = false ----- autoRegister = false
# autoRegister = false
# nameChangeCheck = false
#
# GameProfile logins as cracked until the player invoked the command /premium. Then we could override the existing
# database record.
#
# #### Case 2
#
# nameChangeCheck = true ----- autoRegister = false
# autoRegister = false
# nameChangeCheck = true
#
# Connect the Mojang API and check what UUID the player has (UUID exists => Paid Minecraft account). If that UUID is in
# the database it's an **existing player** and FastLogin can **assume** the player is premium and changed the username.
@@ -79,8 +105,8 @@ premiumUuid: false
# in the meanwhile).
#
# #### Case 3
#
# nameChangeCheck = false ----- autoRegister = true
# autoRegister = true
# nameChangeCheck = false
#
# We will always request a premium authentication if the username is unknown to us, but is in use by a paid Minecraft
# account. This means it's kind of a more aggressive check like nameChangeCheck = true and autoRegister = false, because
@@ -89,8 +115,8 @@ premiumUuid: false
# **Limitation**: see below
#
# #### Case 4
#
# nameChangeCheck = true ----- autoRegister = true
# autoRegister = true
# nameChangeCheck = true
#
# Based on autoRegister it checks if the player name is premium and login using a premium authentication. After that
# fastlogin receives the premium UUID and can update the database record.
@@ -111,6 +137,10 @@ nameChangeCheck: false
# the skin data is included in the Auth-Verification-Response sent by Mojang. If you want to use for other
# players like cracked player, you have to use other plugins.
#
# If you use PaperSpigot - FastLogin will always try to set the skin, even if forwardSkin is set to false
# It is needed to allow premium name change to work correctly
# https://github.com/games647/FastLogin/issues/457
#
# If you want to use skins for your cracked player, you need an additional plugin like
# ChangeSkin, SkinRestorer, ...
forwardSkin: true
@@ -157,6 +187,61 @@ auto-register-unknown: false
# The password of your Minecraft and the password to login in with your auth plugin
autoLogin: true
# Floodgate configuration
# Connecing through Floodgate requires player's to sign in via their Xbox Live account
# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
# Enabling any of these settings might lead to people gaining unauthorized access to other's accounts!
# Automatically log in players connecting through Floodgate.
# Possible values:
# false: Disables auto login for every player connecting through Floodgate
# true: Enables auto login for every player connecting through Floodgate
# linked: Only Bedrock accounts that are linked to a Java account will be logged in automatically
# no-conflict: Bedrock players will only be automatically logged in if the Mojang API reports
# that there is no existing Premium Java MC account with their name.
# This option can be useful if you are not using 'username-prefix' in floodgate/config.yml
# Requires 'autoLogin' to be 'true'
# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
# Enabling this might lead to people gaining unauthorized access to other's accounts!
autoLoginFloodgate: false
# This enables Floodgate players to join the server, even if autoRegister is true and there's an existing
# Java **PREMIUM** account with the same name
#
# Java and Bedrock players will get different UUIDs, so their inventories, location, etc. will be different.
# However, some plugins (such as AuthMe) rely on names instead of UUIDs to identify a player which might cause issues.
# In the case of AuthMe (and other auth plugins), both the Java and the Bedrock player will have the same password.
#
# To prevent conflits from two different players having the same name, it is highly recommended to use a 'username-prefix'
# in floodgate/config.yml
# Note: 'username-prefix' is currently broken when used with FastLogin and ProtocolLib. For more information visit:
# https://github.com/games647/FastLogin/issues/493
# A solution to this is to replace ProtocolLib with ProtocolSupport
#
# Possible values:
# false: Check for Premium Java name conflicts as described in 'autoRegister'
# Note: Linked players have the same name as their Java profile, so the Bedrock player will always conflict
# their own Java account's name. Therefore, setting this to false will prevent any linked player from joining.
# true: Bypass 'autoRegister's name conflict checking
# linked: Bedrock accounts linked to a Java account will be allowed to join with conflicting names
# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
# Enabling this might lead to people gaining unauthorized access to other's accounts!
allowFloodgateNameConflict: false
# Automatically register players connecting through Floodgate.
# autoLoginFloodgate must be available for the player to use this
# Possible values:
# false: Disables auto registering for every player connecting through Floodgate
# true: Enables auto registering for every player connecting through Floodgate
# linked: Only Bedrock accounts that are linked to a Java account will be registered automatically
# no-conflict: Bedrock players will only be automatically registered if the Mojang API reports
# that there is no existing Premium Java MC account with their name.
# This option can be useful if you are not using 'username-prefix' in floodgate/config.yml
# Requires 'autoRegister' to be 'true'
# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
# Enabling this might lead to people gaining unauthorized access to other's accounts!
autoRegisterFloodgate: false
# Database configuration
# Recommended is the use of MariaDB (a better version of MySQL)

View File

@@ -3,7 +3,7 @@
# Source code: https://github.com/games647/FastLogin
#
# You can access the newest locale here:
# https://github.com/games647/FastLogin/blob/master/core/src/main/resources/messages.yml
# https://github.com/games647/FastLogin/blob/main/core/src/main/resources/messages.yml
#
# You want to have language template? Visit the GitHub Wiki here:
# https://github.com/games647/FastLogin/wiki/English
@@ -21,8 +21,8 @@
# ========= Shared (BungeeCord and Bukkit) ============
# Switch mode is activated and a new (non-whitelist) cracked player tries to join
switch-kick-message: '&4Only paid Minecraft whitelisted accounts are allowed to join this server'
# Switch mode is activated and a new cracked player tries to join, who is not namely allowed
switch-kick-message: '&4Only paid Minecraft allowed accounts are allowed to join this server'
# GameProfile activated premium login in order to skip offline authentication
add-premium: '&2Added to the list of premium players'
@@ -53,10 +53,10 @@ player-unknown: '&4Player not in the database'
# The user skipped the authentication, because it was a premium player
auto-login: '&2Auto logged in'
# The user was auto registered on the first join. The user account will be registered to protect it from cracked players
# FastLogin attempted to auto register user. The user account is registered to protect it from cracked players
# If FastLogin is respecting auth plugin IP limit - the registration may have failed, however the message is still displayed
# The password can be used if the mojang servers are down and you still want your premium users to login (PLANNED)
auto-register: '&2Auto registered with password: %password
You may want change it?'
auto-register: '&2Tried auto registering with password: &7%password&2. You may want change it?'
# GameProfile is not able to toggle the premium state of other players
no-permission: '&4Not enough permissions'

View File

@@ -0,0 +1,92 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.games647.fastlogin.core;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class RateLimiterTest {
private static final long THRESHOLD_MILLI = 10;
/**
* Always expired
*/
@Test
public void allowExpire() throws InterruptedException {
int size = 3;
// run twice the size to fill it first and then test it
RateLimiter rateLimiter = new RateLimiter(size, 0);
for (int i = 0; i < size; i++) {
assertTrue("Filling up", rateLimiter.tryAcquire());
}
for (int i = 0; i < size; i++) {
Thread.sleep(1);
assertTrue("Should be expired", rateLimiter.tryAcquire());
}
}
/**
* Too many requests
*/
@Test
public void shoudBlock() {
int size = 3;
// fill the size
RateLimiter rateLimiter = new RateLimiter(size, TimeUnit.SECONDS.toMillis(30));
for (int i = 0; i < size; i++) {
assertTrue("Filling up", rateLimiter.tryAcquire());
}
assertFalse("Should be full and no entry should be expired", rateLimiter.tryAcquire());
}
/**
* Blocked attempts shouldn't replace existing ones.
*/
@Test
public void blockedNotAdded() throws InterruptedException {
// fill the size - 100ms should be reasonable high
RateLimiter rateLimiter = new RateLimiter(1, 100);
assertTrue("Filling up", rateLimiter.tryAcquire());
Thread.sleep(50);
// still is full - should fail
assertFalse("Expired too early", rateLimiter.tryAcquire());
// wait the remaining time and add a threshold, because
Thread.sleep(50 + THRESHOLD_MILLI);
assertTrue("Request not released", rateLimiter.tryAcquire());
}
}

66
pom.xml
View File

@@ -1,3 +1,30 @@
<!--
SPDX-License-Identifier: MIT
The MIT License (MIT)
Copyright (c) 2015-2021 <Your name and contributors>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -52,7 +79,7 @@
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>4.0.0</version>
<version>4.0.4</version>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
</configuration>
@@ -65,6 +92,34 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>4.1</version>
<configuration>
<licenseSets>
<licenseSet>
<multi>
<!-- Machine readable representation -->
<preamble>SPDX-License-Identifier: MIT</preamble>
<header>LICENSE</header>
</multi>
<excludes>
<exclude>src/test/resources/**</exclude>
<exclude>src/main/resources/**</exclude>
</excludes>
</licenseSet>
</licenseSets>
</configuration>
<executions>
<execution>
<goals>
<goal>format</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
@@ -75,4 +130,13 @@
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>