mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +03:00
Авторизация сервера
This commit is contained in:
parent
b77e22ce9f
commit
e77a848843
6 changed files with 205 additions and 5 deletions
|
@ -5,6 +5,7 @@
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import ru.gravit.launcher.LauncherAPI;
|
import ru.gravit.launcher.LauncherAPI;
|
||||||
|
import ru.gravit.launchserver.response.auth.AuthServerResponse;
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
import ru.gravit.launcher.request.RequestException;
|
import ru.gravit.launcher.request.RequestException;
|
||||||
import ru.gravit.launcher.request.RequestType;
|
import ru.gravit.launcher.request.RequestType;
|
||||||
|
@ -53,6 +54,7 @@ public static void registerResponses() {
|
||||||
registerResponse(RequestType.UPDATE_LIST.getNumber(), UpdateListResponse::new);
|
registerResponse(RequestType.UPDATE_LIST.getNumber(), UpdateListResponse::new);
|
||||||
registerResponse(RequestType.UPDATE.getNumber(), UpdateResponse::new);
|
registerResponse(RequestType.UPDATE.getNumber(), UpdateResponse::new);
|
||||||
registerResponse(RequestType.PROFILES.getNumber(), ProfilesResponse::new);
|
registerResponse(RequestType.PROFILES.getNumber(), ProfilesResponse::new);
|
||||||
|
registerResponse(RequestType.SERVERAUTH.getNumber(), AuthServerResponse::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
|
||||||
|
import ru.gravit.launchserver.socket.Client;
|
||||||
import ru.gravit.utils.helper.IOHelper;
|
import ru.gravit.utils.helper.IOHelper;
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
import ru.gravit.utils.helper.SecurityHelper;
|
import ru.gravit.utils.helper.SecurityHelper;
|
||||||
|
@ -60,6 +61,8 @@ public void reply() throws Exception {
|
||||||
debug("Login: '%s', Password: '%s'", login, echo(password.length()));
|
debug("Login: '%s', Password: '%s'", login, echo(password.length()));
|
||||||
AuthProviderResult result;
|
AuthProviderResult result;
|
||||||
AuthProvider provider = server.config.authProvider[auth_id];
|
AuthProvider provider = server.config.authProvider[auth_id];
|
||||||
|
Client clientData = server.sessionManager.getClient(session);
|
||||||
|
clientData.type = Client.Type.USER;
|
||||||
try {
|
try {
|
||||||
if (server.limiter.isLimit(ip)) {
|
if (server.limiter.isLimit(ip)) {
|
||||||
AuthProvider.authError(server.config.authRejectString);
|
AuthProvider.authError(server.config.authRejectString);
|
||||||
|
@ -71,10 +74,17 @@ public void reply() throws Exception {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Collection<SignedObjectHolder<ClientProfile>> profiles = server.getProfiles();
|
Collection<SignedObjectHolder<ClientProfile>> profiles = server.getProfiles();
|
||||||
for (SignedObjectHolder<ClientProfile> p : profiles)
|
for (SignedObjectHolder<ClientProfile> p : profiles) {
|
||||||
if (p.object.getTitle().equals(client))
|
if (p.object.getTitle().equals(client)) {
|
||||||
if (!p.object.isWhitelistContains(login))
|
if (!p.object.isWhitelistContains(login)) {
|
||||||
throw new AuthException(server.config.whitelistRejectString);
|
throw new AuthException(server.config.whitelistRejectString);
|
||||||
|
}
|
||||||
|
clientData.profile = p.object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(clientData.profile == null) {
|
||||||
|
throw new AuthException("You profile not found");
|
||||||
|
}
|
||||||
server.config.hwidHandler.check(HWID.gen(hwid_hdd, hwid_bios, hwid_cpu), result.username);
|
server.config.hwidHandler.check(HWID.gen(hwid_hdd, hwid_bios, hwid_cpu), result.username);
|
||||||
} catch (AuthException | HWIDException e) {
|
} catch (AuthException | HWIDException e) {
|
||||||
requestError(e.getMessage());
|
requestError(e.getMessage());
|
||||||
|
@ -85,6 +95,7 @@ public void reply() throws Exception {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debug("Auth: '%s' -> '%s', '%s'", login, result.username, result.accessToken);
|
debug("Auth: '%s' -> '%s', '%s'", login, result.username, result.accessToken);
|
||||||
|
clientData.isAuth = true;
|
||||||
// Authenticate on server (and get UUID)
|
// Authenticate on server (and get UUID)
|
||||||
UUID uuid;
|
UUID uuid;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
package ru.gravit.launchserver.response.auth;
|
||||||
|
|
||||||
|
import ru.gravit.launcher.profiles.ClientProfile;
|
||||||
|
import ru.gravit.launcher.serialize.HInput;
|
||||||
|
import ru.gravit.launcher.serialize.HOutput;
|
||||||
|
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||||
|
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||||
|
import ru.gravit.launchserver.LaunchServer;
|
||||||
|
import ru.gravit.launchserver.auth.AuthException;
|
||||||
|
import ru.gravit.launchserver.auth.hwid.HWID;
|
||||||
|
import ru.gravit.launchserver.auth.hwid.HWIDException;
|
||||||
|
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||||
|
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||||
|
import ru.gravit.launchserver.response.Response;
|
||||||
|
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
|
||||||
|
import ru.gravit.launchserver.socket.Client;
|
||||||
|
import ru.gravit.utils.helper.IOHelper;
|
||||||
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
import ru.gravit.utils.helper.SecurityHelper;
|
||||||
|
import ru.gravit.utils.helper.VerifyHelper;
|
||||||
|
|
||||||
|
import javax.crypto.BadPaddingException;
|
||||||
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class AuthServerResponse extends Response {
|
||||||
|
private static String echo(int length) {
|
||||||
|
char[] chars = new char[length];
|
||||||
|
Arrays.fill(chars, '*');
|
||||||
|
return new String(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthServerResponse(LaunchServer server, long session, HInput input, HOutput output, String ip) {
|
||||||
|
super(server, session, input, output, ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reply() throws Exception {
|
||||||
|
String login = input.readString(SerializeLimits.MAX_LOGIN);
|
||||||
|
String client = input.readString(SerializeLimits.MAX_CLIENT);
|
||||||
|
int auth_id = input.readInt();
|
||||||
|
if(auth_id + 1 > server.config.authProvider.length || auth_id < 0) auth_id = 0;
|
||||||
|
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("ServerPassword decryption error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(client.length() == 0) requestError("Request error. You is cheater?");
|
||||||
|
// Authenticate
|
||||||
|
debug("ServerLogin: '%s', Password: '%s'", login, echo(password.length()));
|
||||||
|
AuthProviderResult result;
|
||||||
|
AuthProvider provider = server.config.authProvider[auth_id];
|
||||||
|
Client clientData = server.sessionManager.getClient(session);
|
||||||
|
try {
|
||||||
|
if (server.limiter.isLimit(ip)) {
|
||||||
|
AuthProvider.authError(server.config.authRejectString);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result = provider.auth(login, password, ip);
|
||||||
|
if (!VerifyHelper.isValidUsername(result.username)) {
|
||||||
|
AuthProvider.authError(String.format("Illegal result: '%s'", result.username));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Collection<SignedObjectHolder<ClientProfile>> profiles = server.getProfiles();
|
||||||
|
for (SignedObjectHolder<ClientProfile> p : profiles) {
|
||||||
|
if (p.object.getTitle().equals(client)) {
|
||||||
|
if (!p.object.isWhitelistContains(login)) {
|
||||||
|
throw new AuthException(server.config.whitelistRejectString);
|
||||||
|
}
|
||||||
|
clientData.profile = p.object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(clientData.profile == null) {
|
||||||
|
throw new AuthException("You profile not found");
|
||||||
|
}
|
||||||
|
clientData.type = Client.Type.SERVER;
|
||||||
|
} catch (AuthException | HWIDException e) {
|
||||||
|
requestError(e.getMessage());
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
requestError("Internal auth provider error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug("ServerAuth: '%s' -> '%s', '%s'", login, result.username, result.accessToken);
|
||||||
|
clientData.isAuth = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,28 @@
|
||||||
package ru.gravit.launchserver.socket;
|
package ru.gravit.launchserver.socket;
|
||||||
|
|
||||||
|
import ru.gravit.launcher.profiles.ClientProfile;
|
||||||
|
|
||||||
public class Client {
|
public class Client {
|
||||||
public long session;
|
public long session;
|
||||||
|
|
||||||
public long timestamp;
|
public long timestamp;
|
||||||
|
public Type type;
|
||||||
|
public ClientProfile profile;
|
||||||
|
public boolean isAuth;
|
||||||
|
|
||||||
public Client(long session) {
|
public Client(long session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
timestamp = System.currentTimeMillis();
|
timestamp = System.currentTimeMillis();
|
||||||
|
type = Type.USER;
|
||||||
|
isAuth = false;
|
||||||
}
|
}
|
||||||
|
//Данные ваторизации
|
||||||
public void up() {
|
public void up() {
|
||||||
timestamp = System.currentTimeMillis();
|
timestamp = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
public enum Type
|
||||||
|
{
|
||||||
|
SERVER,
|
||||||
|
USER
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package ru.gravit.launcher.request.auth;
|
||||||
|
|
||||||
|
import ru.gravit.launcher.Launcher;
|
||||||
|
import ru.gravit.launcher.LauncherAPI;
|
||||||
|
import ru.gravit.launcher.LauncherConfig;
|
||||||
|
import ru.gravit.launcher.profiles.PlayerProfile;
|
||||||
|
import ru.gravit.launcher.request.Request;
|
||||||
|
import ru.gravit.launcher.request.RequestType;
|
||||||
|
import ru.gravit.launcher.serialize.HInput;
|
||||||
|
import ru.gravit.launcher.serialize.HOutput;
|
||||||
|
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||||
|
import ru.gravit.utils.helper.JVMHelper;
|
||||||
|
import ru.gravit.utils.helper.SecurityHelper;
|
||||||
|
import ru.gravit.utils.helper.VerifyHelper;
|
||||||
|
import ru.zaxar163.GuardBind;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public final class ServerAuthRequest extends Request<ServerAuthRequest.Result> {
|
||||||
|
public static final class Result {
|
||||||
|
@LauncherAPI
|
||||||
|
public final PlayerProfile pp;
|
||||||
|
@LauncherAPI
|
||||||
|
public final String accessToken;
|
||||||
|
|
||||||
|
private Result(PlayerProfile pp, String accessToken) {
|
||||||
|
this.pp = pp;
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String login;
|
||||||
|
|
||||||
|
private final byte[] encryptedPassword;
|
||||||
|
private final int auth_id;
|
||||||
|
|
||||||
|
@LauncherAPI
|
||||||
|
public ServerAuthRequest(LauncherConfig config, String login, byte[] encryptedPassword) {
|
||||||
|
super(config);
|
||||||
|
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
|
||||||
|
this.encryptedPassword = encryptedPassword.clone();
|
||||||
|
auth_id = 0;
|
||||||
|
}
|
||||||
|
@LauncherAPI
|
||||||
|
public ServerAuthRequest(LauncherConfig config, String login, byte[] encryptedPassword, int auth_id) {
|
||||||
|
super(config);
|
||||||
|
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
|
||||||
|
this.encryptedPassword = encryptedPassword.clone();
|
||||||
|
this.auth_id = auth_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LauncherAPI
|
||||||
|
public ServerAuthRequest(String login, byte[] encryptedPassword) {
|
||||||
|
this(null, login, encryptedPassword);
|
||||||
|
}
|
||||||
|
@LauncherAPI
|
||||||
|
public ServerAuthRequest(String login, byte[] encryptedPassword, int auth_id) {
|
||||||
|
this(null, login, encryptedPassword,auth_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getType() {
|
||||||
|
return RequestType.SERVERAUTH.getNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Result requestDo(HInput input, HOutput output) throws IOException {
|
||||||
|
output.writeString(login, SerializeLimits.MAX_LOGIN);
|
||||||
|
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
|
||||||
|
output.writeInt(auth_id);
|
||||||
|
output.writeByteArray(encryptedPassword, SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||||
|
output.flush();
|
||||||
|
|
||||||
|
// Read UUID and access token
|
||||||
|
readError(input);
|
||||||
|
PlayerProfile pp = new PlayerProfile(input);
|
||||||
|
String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH);
|
||||||
|
return new Result(pp, accessToken);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ public enum RequestType implements EnumSerializer.Itf {
|
||||||
LAUNCHER(1), UPDATE(2), UPDATE_LIST(3), // Update requests
|
LAUNCHER(1), UPDATE(2), UPDATE_LIST(3), // Update requests
|
||||||
AUTH(4), JOIN_SERVER(5), CHECK_SERVER(6), // Auth requests
|
AUTH(4), JOIN_SERVER(5), CHECK_SERVER(6), // Auth requests
|
||||||
PROFILE_BY_USERNAME(7), PROFILE_BY_UUID(8), BATCH_PROFILE_BY_USERNAME(9), // Profile requests
|
PROFILE_BY_USERNAME(7), PROFILE_BY_UUID(8), BATCH_PROFILE_BY_USERNAME(9), // Profile requests
|
||||||
PROFILES(10),
|
PROFILES(10),SERVERAUTH(11),
|
||||||
CUSTOM(255); // Custom requests
|
CUSTOM(255); // Custom requests
|
||||||
private static final EnumSerializer<RequestType> SERIALIZER = new EnumSerializer<>(RequestType.class);
|
private static final EnumSerializer<RequestType> SERIALIZER = new EnumSerializer<>(RequestType.class);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue