Add second attemp login -> cracked (Fixes #51)

This commit is contained in:
games647
2016-08-29 17:38:46 +02:00
parent c28d889c1b
commit d20db79f46
16 changed files with 124 additions and 40 deletions

View File

@ -1,3 +1,7 @@
######1.9
* Added second attempt login -> cracked login
######1.8
* Added autoIn importer

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin</artifactId>
<version>1.8</version>
<version>1.9</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -2,11 +2,14 @@ package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.core.FastLoginCore;
import com.google.common.base.Charsets;
import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.io.File;
import java.io.InputStreamReader;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.bukkit.ChatColor;
@ -14,9 +17,30 @@ import org.bukkit.configuration.file.YamlConfiguration;
public class BukkitCore extends FastLoginCore {
public static <K, V> ConcurrentMap<K, V> buildCache(int minutes, int maxSize) {
CompatibleCacheBuilder<Object, Object> builder = CompatibleCacheBuilder.newBuilder();
if (minutes > 0) {
builder.expireAfterWrite(minutes, TimeUnit.MINUTES);
}
if (maxSize > 0) {
builder.maximumSize(maxSize);
}
return builder.build(new CacheLoader<K, V>() {
@Override
public V load(K key) throws Exception {
throw new UnsupportedOperationException("Not supported yet.");
}
});
}
private final FastLoginBukkit plugin;
public BukkitCore(FastLoginBukkit plugin) {
super(BukkitCore.<String, Object>buildCache(5, 0));
this.plugin = plugin;
}

View File

@ -15,7 +15,6 @@ import com.github.games647.fastlogin.bukkit.listener.protocollib.StartPacketList
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
import com.github.games647.fastlogin.bukkit.tasks.DelayedAuthHook;
import com.github.games647.fastlogin.core.FastLoginCore;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.Sets;
import java.security.KeyPair;
@ -23,7 +22,6 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import org.bukkit.entity.Player;
@ -47,7 +45,7 @@ public class FastLoginBukkit extends JavaPlugin {
//this map is thread-safe for async access (Packet Listener)
//SafeCacheBuilder is used in order to be version independent
private final ConcurrentMap<String, BukkitLoginSession> session = buildCache(1, -1);
private final ConcurrentMap<String, BukkitLoginSession> session = BukkitCore.buildCache(1, -1);
//1 minutes should be enough as a timeout for bad internet connection (Server, Client and Mojang)
private BukkitAuthPlugin authPlugin;
@ -60,7 +58,8 @@ public class FastLoginBukkit extends JavaPlugin {
List<String> ipAddresses = getConfig().getStringList("ip-addresses");
int requestLimit = getConfig().getInt("mojang-request-limit");
MojangApiBukkit mojangApi = new MojangApiBukkit(buildCache(10, -1), getLogger(), ipAddresses, requestLimit);
ConcurrentMap<Object, Object> requestCache = BukkitCore.buildCache(10, -1);
MojangApiBukkit mojangApi = new MojangApiBukkit(requestCache, getLogger(), ipAddresses, requestLimit);
core.setMojangApiConnector(mojangApi);
try {
@ -220,23 +219,4 @@ public class FastLoginBukkit extends JavaPlugin {
this.serverStarted = true;
}
}
private <K, V> ConcurrentMap<K, V> buildCache(int minutes, int maxSize) {
CompatibleCacheBuilder<Object, Object> builder = CompatibleCacheBuilder.newBuilder();
if (minutes > 0) {
builder.expireAfterWrite(minutes, TimeUnit.MINUTES);
}
if (maxSize > 0) {
builder.maximumSize(maxSize);
}
return builder.build(new CacheLoader<K, V>() {
@Override
public V load(K key) throws Exception {
throw new UnsupportedOperationException("Not supported yet.");
}
});
}
}

View File

@ -54,7 +54,18 @@ public class NameCheckTask implements Runnable {
if (profile.getUserId() == -1) {
UUID premiumUUID = null;
String ip = player.getAddress().getAddress().getHostAddress();
if (plugin.getCore().getPendingLogins().containsKey(ip + username)
&& plugin.getConfig().getBoolean("secondAttemptCracked")) {
plugin.getLogger().log(Level.INFO, "Second attempt login -> cracked {0}", username);
//first login request failed so make a cracked session
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
plugin.getSessions().put(player.getAddress().toString(), loginSession);
return;
}
//user not exists in the db
try {
boolean isRegistered = plugin.getAuthPlugin().isRegistered(username);
@ -105,6 +116,9 @@ public class NameCheckTask implements Runnable {
boolean success = sentEncryptionRequest(player, serverId, verify);
if (success) {
String ip = player.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogins().put(ip + username, new Object());
BukkitLoginSession playerSession = new BukkitLoginSession(username, serverId, verify, registered, profile);
plugin.getSessions().put(player.getAddress().toString(), playerSession);
//cancel only if the player has a paid account otherwise login as normal offline player

View File

@ -50,6 +50,9 @@ public class VerifyResponseTask implements Runnable {
disconnect(plugin.getCore().getMessage("invalid-requst"), true
, "Player {0} tried to send encryption response at invalid state", fromPlayer.getAddress());
} else {
String ip = fromPlayer.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogins().remove(ip + session.getUsername());
verifyResponse(session);
}
} finally {

View File

@ -31,9 +31,10 @@ public class ProtocolSupportListener implements Listener {
}
String username = loginStartEvent.getName();
InetSocketAddress address = loginStartEvent.getAddress();
//remove old data every time on a new login in order to keep the session only for one person
plugin.getSessions().remove(loginStartEvent.getAddress().toString());
plugin.getSessions().remove(address.toString());
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();
if (authPlugin == null) {
@ -43,6 +44,18 @@ public class ProtocolSupportListener implements Listener {
PlayerProfile profile = plugin.getCore().getStorage().loadProfile(username);
if (profile != null) {
if (profile.getUserId() == -1) {
String ip = address.getAddress().getHostAddress();
if (plugin.getCore().getPendingLogins().containsKey(ip + username)
&& plugin.getConfig().getBoolean("secondAttemptCracked")) {
plugin.getLogger().log(Level.INFO, "Second attempt login -> cracked {0}", username);
//first login request failed so make a cracked session
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
plugin.getSessions().put(address.toString(), loginSession);
return;
}
UUID premiumUUID = null;
//user not exists in the db
@ -70,7 +83,7 @@ public class ProtocolSupportListener implements Listener {
//no premium check passed so we save it as a cracked player
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
plugin.getSessions().put(loginStartEvent.getAddress().toString(), loginSession);
plugin.getSessions().put(address.toString(), loginSession);
} catch (Exception ex) {
plugin.getLogger().log(Level.SEVERE, "Failed to query isRegistered", ex);
}
@ -78,7 +91,7 @@ public class ProtocolSupportListener implements Listener {
startPremiumSession(username, loginStartEvent, true, profile);
} else {
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
plugin.getSessions().put(loginStartEvent.getAddress().toString(), loginSession);
plugin.getSessions().put(address.toString(), loginSession);
}
}
}
@ -90,17 +103,23 @@ public class ProtocolSupportListener implements Listener {
InetSocketAddress address = propertiesResolveEvent.getAddress();
BukkitLoginSession session = plugin.getSessions().get(address.toString());
if (session != null) {
String ip = address.getAddress().getHostAddress();
plugin.getCore().getPendingLogins().remove(ip + session.getUsername());
session.setVerified(true);
}
}
}
private void startPremiumSession(String playerName, PlayerLoginStartEvent loginStartEvent, boolean registered
private void startPremiumSession(String username, PlayerLoginStartEvent loginStartEvent, boolean registered
, PlayerProfile playerProfile) {
loginStartEvent.setOnlineMode(true);
InetSocketAddress address = loginStartEvent.getAddress();
BukkitLoginSession playerSession = new BukkitLoginSession(playerName, null, null, registered, playerProfile);
String ip = address.getAddress().getHostAddress();
plugin.getCore().getPendingLogins().put(ip + username, new Object());
BukkitLoginSession playerSession = new BukkitLoginSession(username, null, null, registered, playerProfile);
plugin.getSessions().put(address.toString(), playerSession);
if (plugin.getConfig().getBoolean("premiumUuid")) {
loginStartEvent.setUseOnlineModeUUID(true);

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin</artifactId>
<version>1.8</version>
<version>1.9</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -1,6 +1,7 @@
package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.core.FastLoginCore;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.io.File;
@ -8,10 +9,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
@ -22,6 +24,8 @@ public class BungeeCore extends FastLoginCore {
private final FastLoginBungee plugin;
public BungeeCore(FastLoginBungee plugin) {
super(CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).<String, Object>build().asMap());
this.plugin = plugin;
}

View File

@ -59,6 +59,9 @@ public class PlayerConnectionListener implements Listener {
PendingConnection connection = loginEvent.getConnection();
String username = connection.getName();
if (connection.isOnlineMode()) {
String ip = connection.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogins().remove(ip + username);
LoginSession session = plugin.getSession().get(connection);
PlayerProfile playerProfile = session.getProfile();
playerProfile.setUuid(connection.getUniqueId());

View File

@ -27,13 +27,23 @@ public class AsyncPremiumCheck implements Runnable {
plugin.getSession().remove(connection);
String username = connection.getName();
try {
PlayerProfile profile = plugin.getCore().getStorage().loadProfile(username);
if (profile == null) {
return;
}
PlayerProfile profile = plugin.getCore().getStorage().loadProfile(username);
if (profile == null) {
return;
}
try {
if (profile.getUserId() == -1) {
String ip = connection.getAddress().getAddress().getHostAddress();
if (plugin.getCore().getPendingLogins().containsKey(ip + username)
&& plugin.getConfig().getBoolean("secondAttemptCracked")) {
plugin.getLogger().log(Level.INFO, "Second attempt login -> cracked {0}", username);
//first login request failed so make a cracked session
plugin.getSession().put(connection, new BungeeLoginSession(username, false, profile));
return;
}
UUID premiumUUID = null;
if (plugin.getConfig().getBoolean("nameChangeCheck") || plugin.getConfig().getBoolean("autoRegister")) {
premiumUUID = plugin.getCore().getMojangApiConnector().getPremiumUUID(username);
@ -89,5 +99,8 @@ public class AsyncPremiumCheck implements Runnable {
private void requestPremiumLogin(PendingConnection con, PlayerProfile profile, String username, boolean register) {
con.setOnlineMode(true);
plugin.getSession().put(con, new BungeeLoginSession(username, register, profile));
String ip = con.getAddress().getAddress().getHostAddress();
plugin.getCore().getPendingLogins().put(ip + username, new Object());
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin</artifactId>
<version>1.8</version>
<version>1.9</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -11,6 +11,7 @@ import java.sql.SQLException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -30,9 +31,16 @@ public abstract class FastLoginCore {
}
protected final Map<String, String> localeMessages = new ConcurrentHashMap<>();
private final ConcurrentMap<String, Object> pendingLogins;
private MojangApiConnector mojangApiConnector;
private AuthStorage storage;
public FastLoginCore(ConcurrentMap<String, Object> pendingLogins) {
this.pendingLogins = pendingLogins;
}
public void setMojangApiConnector(MojangApiConnector mojangApiConnector) {
this.mojangApiConnector = mojangApiConnector;
}
@ -110,6 +118,10 @@ public abstract class FastLoginCore {
return false;
}
public ConcurrentMap<String, Object> getPendingLogins() {
return pendingLogins;
}
public void close() {
if (storage != null) {
storage.close();

View File

@ -21,6 +21,14 @@
# For more information: https://github.com/games647/FastLogin#why-do-players-have-to-invoke-a-command
autoRegister: 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".
#
# If you activate this, we are remembering this player and do not force another premium authentication if the player
# tries to join again, so the player could join as cracked player.
secondAttemptCracked: false
# If this plugin detected that a player has a premium, it can also set the associated
# uuid from that account. So if the players changes their usernames, they will still have
# the same playerdata (inventory, permissions, ...)

View File

@ -8,7 +8,7 @@
<packaging>pom</packaging>
<name>FastLogin</name>
<version>1.8</version>
<version>1.9</version>
<inceptionYear>2015</inceptionYear>
<url>https://www.spigotmc.org/resources/fastlogin.14153/</url>
<description>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.github.games647</groupId>
<artifactId>fastlogin</artifactId>
<version>1.8</version>
<version>1.9</version>
<relativePath>../pom.xml</relativePath>
</parent>