Newer
Older
KeeperJerry_Launcher / LaunchServer / source / response / auth / AuthResponse.java
package launchserver.response.auth;

import launcher.helper.IOHelper;
import launcher.helper.LogHelper;
import launcher.helper.SecurityHelper;
import launcher.helper.VerifyHelper;
import launcher.serialize.HInput;
import launcher.serialize.HOutput;
import launcher.serialize.config.entry.StringConfigEntry;
import launchserver.LaunchServer;
import launchserver.auth.AuthException;
import launchserver.auth.limiter.AuthLimiterIPConfig;
import launchserver.auth.provider.AuthProvider;
import launchserver.auth.provider.AuthProviderResult;
import launchserver.response.Response;
import launchserver.response.profile.ProfileByUUIDResponse;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import java.util.Arrays;
import java.util.UUID;

public final class AuthResponse extends Response
{
    private final String ip;

    public AuthResponse(LaunchServer server, HInput input, HOutput output, String ip)
    {
        super(server, ip, input, output);
        this.ip = ip;
    }

    private static String echo(int length)
    {
        char[] chars = new char[length];
        Arrays.fill(chars, '*');
        return new String(chars);
    }

    @Override
    public void reply() throws Throwable
    {
        String login = input.readString(255);
        byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH);

        // Decrypt password
        String password;
        try
        {
            password = IOHelper.decode(SecurityHelper.newRSADecryptCipher(server.privateKey).
                    doFinal(encryptedPassword));
        }
        catch (IllegalBlockSizeException | BadPaddingException ignored)
        {
            requestError("Password decryption error");
            return;
        }

        // Authenticate
        debug("Login: '%s', Password: '%s'", login, echo(password.length()));
        AuthProviderResult result;
        try
        {
            // Лесенка чтоб ее
            if (server.config.authLimit)
            {
                if (AuthLimiterIPConfig.Instance.getBlockIp().stream().anyMatch(s -> s.equals(ip)) && server.config.authLimitConfig.useBlockIp)
                {
                    AuthProvider.authError(server.config.authLimitConfig.authBannedString);
                    return;
                }

                if (AuthLimiterIPConfig.Instance.getAllowIp().stream().noneMatch(s -> s.equals(ip)))
                {
                    if (server.config.authLimitConfig.onlyAllowIp)
                    {
                        AuthProvider.authError(server.config.authLimitConfig.authNotWhitelistString);
                        return;
                    }

                    if (server.config.authLimitConfig.useAllowIp)
                    {
                        if (server.limiter.isLimit(ip))
                        {
                            AuthProvider.authError(server.config.authLimitConfig.authRejectString);
                            return;
                        }
                    }
                }
            }

            result = server.config.authProvider.auth(login, password, ip);
            if (!VerifyHelper.isValidUsername(result.username))
            {
                AuthProvider.authError(String.format("Illegal result: '%s'", result.username));
                return;
            }
        }
        catch (AuthException e)
        {
            requestError(e.getMessage());
            return;
        }
        catch (Throwable exc)
        {
            LogHelper.error(exc);
            requestError("Internal auth provider error");
            return;
        }
        debug("Auth: '%s' -> '%s', '%s'", login, result.username, result.accessToken);

        // Authenticate on server (and get UUID)
        UUID uuid;
        try
        {
            uuid = server.config.authHandler.auth(result);
        }
        catch (AuthException e)
        {
            requestError(e.getMessage());
            return;
        }
        catch (Throwable exc)
        {
            LogHelper.error(exc);
            requestError("Internal auth handler error");
            return;
        }
        writeNoError(output);

        // Write profile and UUID
        ProfileByUUIDResponse.getProfile(server, uuid, result.username).write(output);
        output.writeInt(result.accessToken.length());
        output.writeASCII(result.accessToken, -result.accessToken.length());
    }
}