SetupHandlerSupplier interface
Пакет: com.hypixel.hytale.server.core.io.handlers.login
Файл: com/hypixel/hytale/server/core/io/handlers/login/PasswordPacketHandler.java
Методы (1)
| Модификаторы | Возврат | Сигнатура |
|---|---|---|
abstract |
PacketHandler |
createPacketHandler create(ChannelConnection var1, ProtocolVersion var2, String var3, PlayerAuthentication var4) |
Исходный код
Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.io.handlers.login;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.protocol.ToServerPacket;
class="kw">import com.hypixel.hytale.protocol.io.ChannelConnection;
class="kw">import com.hypixel.hytale.protocol.io.ConnectionHandler;
class="kw">import com.hypixel.hytale.protocol.packets.auth.PasswordAccepted;
class="kw">import com.hypixel.hytale.protocol.packets.auth.PasswordRejected;
class="kw">import com.hypixel.hytale.protocol.packets.auth.PasswordResponse;
class="kw">import com.hypixel.hytale.protocol.packets.connection.ClientDisconnect;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.core.HytaleServerConfig;
class="kw">import com.hypixel.hytale.server.core.Message;
class="kw">import com.hypixel.hytale.server.core.auth.PlayerAuthentication;
class="kw">import com.hypixel.hytale.server.core.io.PacketHandler;
class="kw">import com.hypixel.hytale.server.core.io.ProtocolVersion;
class="kw">import com.hypixel.hytale.server.core.io.handlers.GenericConnectionPacketHandler;
class="kw">import java.nio.charset.StandardCharsets;
class="kw">import java.security.MessageDigest;
class="kw">import java.security.NoSuchAlgorithmException;
class="kw">import java.security.SecureRandom;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">public class PasswordPacketHandler class="kw">extends GenericConnectionPacketHandler {
class="kw">private class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
class="kw">private class="kw">static class="kw">final int MAX_PASSWORD_ATTEMPTS = 3;
class="kw">private class="kw">static class="kw">final int CHALLENGE_LENGTH = 32;
@Nonnull
class="kw">private class="kw">final PlayerAuthentication pendingAuth;
class="kw">private byte[] passwordChallenge;
class="kw">private class="kw">final PasswordPacketHandler.SetupHandlerSupplier setupHandlerSupplier;
class="kw">private int attemptsRemaining = 3;
class="kw">public PasswordPacketHandler(
@Nonnull ChannelConnection var1,
@Nonnull ProtocolVersion var2,
@Nonnull String var3,
@Nonnull PlayerAuthentication var4,
@Nullable byte[] var5,
@Nonnull PasswordPacketHandler.SetupHandlerSupplier var6
) {
super(var1, var2, var3);
this.pendingAuth = var4;
this.passwordChallenge = var5;
this.setupHandlerSupplier = var6;
}
@Nonnull
@Override
class="kw">public String getIdentifier() {
class="kw">return "{Password(" + this.getChannel().formatRemoteAddress() + "), " + this.pendingAuth.getUsername() + "}";
}
@Override
class="kw">public void registered0(ConnectionHandler var1) {
HytaleServerConfig.TimeoutProfile var2 = HytaleServer.get().getConfig().getConnectionTimeouts();
if (this.passwordChallenge != null && this.passwordChallenge.length != 0) {
LOGGER.at(Level.FINE).log("Waiting for password response from %s", this.pendingAuth.getUsername());
this.enterStage("password", var2.getPassword(), () -> !this.registered);
} else {
LOGGER.at(Level.FINE).log("No password required for %s, proceeding to setup", this.pendingAuth.getUsername());
this.proceedToSetup();
}
}
@Override
class="kw">public void accept(@Nonnull ToServerPacket var1) {
class="kw">switch (var1.getId()) {
case 1:
this.handle((ClientDisconnect)var1);
break;
case 15:
this.handle((PasswordResponse)var1);
break;
class="kw">default:
this.disconnect(Message.translation("client.general.disconnect.protocol.unexpectedPacket").param("packetId", var1.getId()));
}
}
class="kw">public void handle(@Nonnull ClientDisconnect var1) {
this.disconnectReason.setClientDisconnectType(var1.type);
LOGGER.at(Level.INFO)
.log(
"%s (%s) at %s left with reason: %s - %s",
this.pendingAuth.getUuid(),
this.pendingAuth.getUsername(),
this.getChannel().formatRemoteAddress(),
var1.type.name(),
var1.reason.name()
);
this.getChannel().closeApplicationConnection();
}
class="kw">public void handle(@Nonnull PasswordResponse var1) {
this.clearTimeout();
if (this.passwordChallenge != null && this.passwordChallenge.length != 0) {
byte[] var2 = var1.hash;
if (var2 != null && var2.length != 0) {
String var3 = HytaleServer.get().getConfig().getPassword();
if (var3 != null && !var3.isEmpty()) {
byte[] var4 = computePasswordHash(this.passwordChallenge, var3);
if (var4 == null) {
LOGGER.at(Level.SEVERE).log("Failed to compute password hash");
this.disconnect(Message.translation("client.general.disconnect.serverError"));
} else if (!MessageDigest.isEqual(var4, var2)) {
this.attemptsRemaining--;
LOGGER.at(Level.WARNING)
.log(
"Invalid password from %s (%s), %d attempts remaining",
this.pendingAuth.getUsername(),
this.getChannel().formatRemoteAddress(),
this.attemptsRemaining
);
if (this.attemptsRemaining <= 0) {
this.disconnect(Message.translation("client.general.disconnect.tooManyPasswordAttempts"));
} else {
this.passwordChallenge = generateChallenge();
this.write(new PasswordRejected(this.passwordChallenge, this.attemptsRemaining));
HytaleServerConfig.TimeoutProfile var5 = HytaleServer.get().getConfig().getConnectionTimeouts();
this.continueStage("password", var5.getPassword(), () -> !this.registered);
}
} else {
LOGGER.at(Level.INFO).log("Password accepted for %s (%s)", this.pendingAuth.getUsername(), this.pendingAuth.getUuid());
this.write(new PasswordAccepted());
this.proceedToSetup();
}
} else {
LOGGER.at(Level.SEVERE).log("Password validation failed - no password configured but challenge was sent");
this.disconnect(Message.translation("client.general.disconnect.serverConfigError"));
}
} else {
LOGGER.at(Level.WARNING).log("Received empty password hash from %s", this.getChannel().formatRemoteAddress());
this.disconnect(Message.translation("client.general.disconnect.invalidPasswordResponse"));
}
} else {
LOGGER.at(Level.WARNING).log("Received unexpected PasswordResponse from %s - no password required", this.getChannel().formatRemoteAddress());
this.disconnect(Message.translation("client.general.disconnect.protocol.unexpectedPasswordResponse"));
}
}
class="kw">private class="kw">static byte[] generateChallenge() {
byte[] var0 = new byte[32];
new SecureRandom().nextBytes(var0);
class="kw">return var0;
}
class="kw">private void proceedToSetup() {
this.auth = this.pendingAuth;
LOGGER.at(Level.INFO)
.log("Connection complete for %s (%s) (SNI: %s), transitioning to setup", this.auth.getUsername(), this.auth.getUuid(), this.getSniHostname());
this.getChannel().setChannelHandler(this.setupHandlerSupplier.create(this.getChannel(), this.protocolVersion, this.language, this.auth));
}
@Nullable
class="kw">private class="kw">static byte[] computePasswordHash(byte[] var0, String var1) {
try {
MessageDigest var2 = MessageDigest.getInstance("SHA-256");
var2.update(var0);
var2.update(var1.getBytes(StandardCharsets.UTF_8));
class="kw">return var2.digest();
} catch (NoSuchAlgorithmException var3) {
class="kw">return null;
}
}
@FunctionalInterface
class="kw">public class="kw">interface SetupHandlerSupplier {
PacketHandler create(ChannelConnection var1, ProtocolVersion var2, String var3, PlayerAuthentication var4);
}
}