Авторизация сервера

This commit is contained in:
Gravit 2018-09-27 04:18:26 +07:00
parent b77e22ce9f
commit e77a848843
6 changed files with 205 additions and 5 deletions

View file

@ -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

View file

@ -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 {

View file

@ -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;
}
}

View file

@ -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
}
} }

View file

@ -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);
}
}

View file

@ -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);