[REFRACTOR] Удалены все запросы и большинство ответов по протоколу сашка

This commit is contained in:
Gravit 2019-04-04 18:40:24 +07:00
parent d805fb7515
commit dbb07dee79
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
46 changed files with 39 additions and 1506 deletions

View file

@ -1,6 +1,6 @@
package ru.gravit.launchserver.auth.protect;
import ru.gravit.launchserver.response.auth.AuthResponse;
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
import ru.gravit.utils.helper.SecurityHelper;
public class NoProtectHandler extends ProtectHandler {

View file

@ -1,6 +1,6 @@
package ru.gravit.launchserver.auth.protect;
import ru.gravit.launchserver.response.auth.AuthResponse;
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
import ru.gravit.utils.helper.VerifyHelper;
import java.util.Map;

View file

@ -200,7 +200,7 @@ public Path process(Path inputJar) throws IOException {
byte[] launcherConfigBytes;
try (ByteArrayOutputStream configArray = IOHelper.newByteArrayOutput()) {
try (HOutput configOutput = new HOutput(configArray)) {
new LauncherConfig(server.config.getAddress(), server.config.port, server.publicKey, runtime)
new LauncherConfig(server.config.netty.address, server.publicKey, runtime)
.write(configOutput);
}
launcherConfigBytes = configArray.toByteArray();

View file

@ -4,8 +4,8 @@
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.auth.provider.AuthProvider;
import ru.gravit.launchserver.response.auth.AuthResponse;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
import java.util.ArrayList;
import java.util.HashMap;

View file

@ -1,8 +1,8 @@
package ru.gravit.launchserver.manangers.hook;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.response.auth.AuthResponse;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
import java.util.HashSet;
import java.util.Set;

View file

@ -5,11 +5,6 @@
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.response.admin.ExecCommandResponse;
import ru.gravit.launchserver.response.auth.*;
import ru.gravit.launchserver.response.profile.BatchProfileByUsernameResponse;
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
import ru.gravit.launchserver.response.profile.ProfileByUsernameResponse;
import ru.gravit.launchserver.response.update.*;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.utils.helper.LogHelper;
@ -37,23 +32,8 @@ public static void registerResponse(int type, Factory<?> factory) {
public static void registerResponses() {
registerResponse(RequestType.PING.getNumber(), PingResponse::new);
registerResponse(RequestType.AUTH.getNumber(), AuthResponse::new);
registerResponse(RequestType.CHECK_SERVER.getNumber(), CheckServerResponse::new);
registerResponse(RequestType.JOIN_SERVER.getNumber(), JoinServerResponse::new);
registerResponse(RequestType.BATCH_PROFILE_BY_USERNAME.getNumber(), BatchProfileByUsernameResponse::new);
registerResponse(RequestType.PROFILE_BY_USERNAME.getNumber(), ProfileByUsernameResponse::new);
registerResponse(RequestType.PROFILE_BY_UUID.getNumber(), ProfileByUUIDResponse::new);
registerResponse(RequestType.LEGACYLAUNCHER.getNumber(), LegacyLauncherResponse::new);
registerResponse(RequestType.LAUNCHER.getNumber(), LauncherResponse::new);
registerResponse(RequestType.UPDATE_LIST.getNumber(), UpdateListResponse::new);
registerResponse(RequestType.UPDATE.getNumber(), UpdateResponse::new);
registerResponse(RequestType.PROFILES.getNumber(), ProfilesResponse::new);
registerResponse(RequestType.SERVERAUTH.getNumber(), AuthServerResponse::new);
registerResponse(RequestType.SETPROFILE.getNumber(), SetProfileResponse::new);
registerResponse(RequestType.CHANGESERVER.getNumber(), ChangeServerResponse::new);
registerResponse(RequestType.EXECCOMMAND.getNumber(), ExecCommandResponse::new);
}

View file

@ -1,42 +0,0 @@
package ru.gravit.launchserver.response.admin;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launcher.serialize.SerializeLimits;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.utils.helper.LogHelper;
import java.io.IOException;
public class ExecCommandResponse extends Response {
public ExecCommandResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws Exception {
Client clientData = server.sessionManager.getClient(session);
if (!clientData.isAuth || !clientData.permissions.canAdmin || !server.config.enableRcon)
requestError("Access denied");
writeNoError(output);
String cmd = input.readString(SerializeLimits.MAX_COMMAND);
LogHelper.OutputEnity loutput = new LogHelper.OutputEnity(message -> {
try {
output.writeBoolean(true);
output.writeString(message, SerializeLimits.MAX_COMMAND);
} catch (IOException e) {
LogHelper.error(e);
}
}, LogHelper.OutputTypes.PLAIN);
LogHelper.addOutput(loutput);
try {
server.commandHandler.eval(cmd, false);
output.writeBoolean(false);
} finally {
LogHelper.removeOutput(loutput);
}
writeNoError(output);
}
}

View file

@ -1,154 +0,0 @@
package ru.gravit.launchserver.response.auth;
import ru.gravit.launcher.OshiHWID;
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.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.auth.AuthProviderPair;
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 AuthResponse extends Response {
private static String echo(int length) {
char[] chars = new char[length];
Arrays.fill(chars, '*');
return new String(chars);
}
public AuthResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
public static class AuthContext {
public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, String ip, boolean isServerAuth) {
this.session = session;
this.login = login;
this.password_lenght = password_lenght;
this.customText = customText;
this.client = client;
this.hwid = hwid;
this.ip = ip;
this.isServerAuth = isServerAuth;
}
public long session;
public String login;
public int password_lenght; //Use AuthProvider for get password
public String client;
public String hwid;
public String customText;
public String ip;
public boolean isServerAuth;
}
@Override
public void reply() throws Exception {
String login = input.readString(SerializeLimits.MAX_LOGIN);
boolean isClient = input.readBoolean();
String client = null;
if (isClient)
client = input.readString(SerializeLimits.MAX_CLIENT);
String auth_id = input.readString(SerializeLimits.MAX_QUEUE_SIZE);
String hwid_str = input.readString(SerializeLimits.MAX_HWID_STR);
byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH);
String customText = input.readString(SerializeLimits.MAX_CUSTOM_TEXT);
// 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;
AuthProviderPair pair;
if (auth_id.isEmpty()) pair = server.config.getAuthProviderPair();
else pair = server.config.getAuthProviderPair(auth_id);
if (pair == null) requestError("Auth type not found");
AuthProvider provider = pair.provider;
clientData.type = Client.Type.USER;
AuthContext context = new AuthContext(session, login, password.length(), customText, client, hwid_str, ip, false);
try {
server.authHookManager.preHook(context, clientData);
if (!clientData.checkSign) {
throw new AuthException("You must using checkLauncher");
}
provider.preAuth(login, password, customText, ip);
result = provider.auth(login, password, ip);
if (!VerifyHelper.isValidUsername(result.username)) {
AuthProvider.authError(String.format("Illegal result: '%s'", result.username));
return;
}
if (isClient) {
Collection<ClientProfile> profiles = server.getProfiles();
for (ClientProfile p : profiles) {
if (p.getTitle().equals(client)) {
if (!p.isWhitelistContains(login)) {
throw new AuthException(server.config.whitelistRejectString);
}
clientData.profile = p;
}
}
if (clientData.profile == null) {
throw new AuthException("Your profile is not found");
}
}
server.config.hwidHandler.check(OshiHWID.gson.fromJson(hwid_str, OshiHWID.class), result.username);
server.authHookManager.postHook(context, clientData);
} catch (AuthException | HWIDException e) {
if (e.getMessage() == null) LogHelper.error(e);
requestError(e.getMessage());
return;
} catch (Exception e) {
LogHelper.error(e);
requestError("Internal auth provider error");
return;
}
debug("Auth: '%s' -> '%s', '%s'", login, result.username, result.accessToken);
clientData.isAuth = true;
clientData.permissions = result.permissions;
clientData.username = result.username;
clientData.auth_id = auth_id;
clientData.updateAuth();
// Authenticate on server (and get UUID)
UUID uuid;
try {
uuid = pair.handler.auth(result);
} catch (AuthException e) {
requestError(e.getMessage());
return;
} catch (Exception e) {
LogHelper.error(e);
requestError("Internal auth handler error");
return;
}
String protectToken = server.config.protectHandler.generateSecureToken(context);
writeNoError(output);
// Write profile and UUID
ProfileByUUIDResponse.getProfile(server, uuid, result.username, client, clientData.auth.textureProvider).write(output);
output.writeASCII(result.accessToken, -SecurityHelper.TOKEN_STRING_LENGTH);
clientData.permissions.write(output);
output.writeString(protectToken, SerializeLimits.MAX_CUSTOM_TEXT);
}
}

View file

@ -1,98 +0,0 @@
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.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.auth.AuthProviderPair;
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.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;
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, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws Exception {
String login = input.readString(SerializeLimits.MAX_LOGIN);
String client = input.readString(SerializeLimits.MAX_CLIENT);
String auth_id = input.readString(SerializeLimits.MAX_QUEUE_SIZE);
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;
}
// Authenticate
debug("ServerLogin: '%s', Password: '%s'", login, echo(password.length()));
AuthProviderResult result;
AuthProviderPair pair;
if (auth_id.isEmpty()) pair = server.config.getAuthProviderPair();
else pair = server.config.getAuthProviderPair(auth_id);
if (pair == null) requestError("Auth type not found");
AuthProvider provider = pair.provider;
AuthResponse.AuthContext context = new AuthResponse.AuthContext(session, login, password.length(), null, client, null, ip, true);
try {
server.authHookManager.preHook(context, clientData);
result = provider.auth(login, password, ip);
if (!VerifyHelper.isValidUsername(result.username)) {
AuthProvider.authError(String.format("Illegal result: '%s'", result.username));
return;
}
Collection<ClientProfile> profiles = server.getProfiles();
for (ClientProfile p : profiles) {
if (p.getTitle().equals(client)) {
clientData.profile = p;
}
}
if (clientData.profile == null) {
throw new AuthException("Your profile is not found");
}
clientData.permissions = server.config.permissionsHandler.getPermissions(login);
if (!clientData.permissions.canServer) {
throw new AuthException("Your account cannot be a server");
}
clientData.type = Client.Type.SERVER;
clientData.username = result.username;
server.authHookManager.postHook(context, clientData);
} 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;
clientData.auth_id = auth_id;
clientData.updateAuth();
writeNoError(output);
clientData.permissions.write(output);
}
}

View file

@ -1,28 +0,0 @@
package ru.gravit.launchserver.response.auth;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.socket.Client;
public class ChangeServerResponse extends Response {
public static boolean needChange = false;
public static String address;
public static int port;
public ChangeServerResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws Exception {
writeNoError(output);
output.writeBoolean(needChange);
//if true
if (needChange) {
output.writeString(address, 255);
output.writeInt(port);
}
}
}

View file

@ -1,53 +0,0 @@
package ru.gravit.launchserver.response.auth;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launcher.serialize.SerializeLimits;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.utils.helper.LogHelper;
import ru.gravit.utils.helper.VerifyHelper;
import java.io.IOException;
import java.util.UUID;
public final class CheckServerResponse extends Response {
public CheckServerResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws IOException {
String username = VerifyHelper.verifyUsername(input.readString(SerializeLimits.MAX_LOGIN));
String serverID = VerifyHelper.verifyServerID(input.readASCII(41)); // With minus sign
String client = input.readString(SerializeLimits.MAX_CLIENT);
debug("Username: %s, Server ID: %s", username, serverID);
if (!clientData.isAuth || clientData.type != Client.Type.SERVER) {
requestError("Access denied");
return;
}
// Try check server with auth handler
UUID uuid;
try {
server.authHookManager.checkServerHook(username, serverID);
uuid = clientData.auth.handler.checkServer(username, serverID);
} catch (AuthException e) {
requestError(e.getMessage());
return;
} catch (Exception e) {
LogHelper.error(e);
requestError("Internal auth handler error");
return;
}
writeNoError(output);
// Write profile and UUID
output.writeBoolean(uuid != null);
if (uuid != null)
ProfileByUUIDResponse.getProfile(server, uuid, username, client, clientData.auth.textureProvider).write(output);
}
}

View file

@ -1,50 +0,0 @@
package ru.gravit.launchserver.response.auth;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launcher.serialize.SerializeLimits;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.utils.helper.LogHelper;
import ru.gravit.utils.helper.SecurityHelper;
import ru.gravit.utils.helper.VerifyHelper;
import java.io.IOException;
public final class JoinServerResponse extends Response {
public JoinServerResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws IOException {
String username = VerifyHelper.verifyUsername(input.readString(SerializeLimits.MAX_LOGIN));
String accessToken = SecurityHelper.verifyToken(input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH));
String serverID = VerifyHelper.verifyServerID(input.readASCII(SerializeLimits.MAX_SERVERID)); // With minus sign
if (!clientData.isAuth || clientData.type != Client.Type.USER) {
requestError("Access denied");
return;
}
// Try join server with auth handler
debug("Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID);
boolean success;
try {
server.authHookManager.joinServerHook(username, accessToken, serverID);
success = clientData.auth.handler.joinServer(username, accessToken, serverID);
} catch (AuthException e) {
requestError(e.getMessage());
return;
} catch (Exception e) {
LogHelper.error(e);
requestError("Internal auth handler error");
return;
}
writeNoError(output);
// Write response
output.writeBoolean(success);
}
}

View file

@ -1,36 +0,0 @@
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.launchserver.LaunchServer;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.socket.Client;
import java.util.Collection;
public class SetProfileResponse extends Response {
public SetProfileResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws Exception {
String client = input.readString(SerializeLimits.MAX_CLIENT);
if (!clientData.isAuth) requestError("You not auth");
Collection<ClientProfile> profiles = server.getProfiles();
for (ClientProfile p : profiles) {
if (p.getTitle().equals(client)) {
if (!p.isWhitelistContains(clientData.username)) {
requestError(server.config.whitelistRejectString);
return;
}
clientData.profile = p;
writeNoError(output);
output.writeBoolean(true);
break;
}
}
}
}

View file

@ -1,35 +0,0 @@
package ru.gravit.launchserver.response.profile;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launcher.serialize.SerializeLimits;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.utils.helper.VerifyHelper;
import java.io.IOException;
import java.util.Arrays;
public final class BatchProfileByUsernameResponse extends Response {
public BatchProfileByUsernameResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws IOException {
int length = input.readLength(SerializeLimits.MAX_BATCH_SIZE);
String[] usernames = new String[length];
String[] clients = new String[length];
for (int i = 0; i < usernames.length; i++) {
usernames[i] = VerifyHelper.verifyUsername(input.readString(64));
clients[i] = input.readString(SerializeLimits.MAX_CLIENT);
}
debug("Usernames: " + Arrays.toString(usernames));
// Respond with profiles array
for (int i = 0; i < usernames.length; i++)
ProfileByUsernameResponse.writeProfile(server, output, usernames[i], clients[i], clientData.auth);
}
}

View file

@ -1,62 +0,0 @@
package ru.gravit.launchserver.response.profile;
import ru.gravit.launcher.profiles.PlayerProfile;
import ru.gravit.launcher.profiles.Texture;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launcher.serialize.SerializeLimits;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.texture.TextureProvider;
import ru.gravit.utils.helper.LogHelper;
import java.io.IOException;
import java.util.UUID;
public final class ProfileByUUIDResponse extends Response {
public static PlayerProfile getProfile(LaunchServer server, UUID uuid, String username, String client, TextureProvider textureProvider) {
// Get skin texture
Texture skin;
try {
skin = textureProvider.getSkinTexture(uuid, username, client);
} catch (IOException e) {
LogHelper.error(new IOException(String.format("Can't get skin texture: '%s'", username), e));
skin = null;
}
// Get cloak texture
Texture cloak;
try {
cloak = textureProvider.getCloakTexture(uuid, username, client);
} catch (IOException e) {
LogHelper.error(new IOException(String.format("Can't get cloak texture: '%s'", username), e));
cloak = null;
}
// Return combined profile
return new PlayerProfile(uuid, username, skin, cloak);
}
public ProfileByUUIDResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws IOException {
UUID uuid = input.readUUID();
debug("UUID: " + uuid);
String client = input.readString(SerializeLimits.MAX_CLIENT);
// Verify has such profile
String username = clientData.auth.handler.uuidToUsername(uuid);
if (username == null) {
output.writeBoolean(false);
return;
}
// Write profile
output.writeBoolean(true);
getProfile(server, uuid, username, client, clientData.auth.textureProvider).write(output);
}
}

View file

@ -1,41 +0,0 @@
package ru.gravit.launchserver.response.profile;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launcher.serialize.SerializeLimits;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthProviderPair;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.utils.helper.VerifyHelper;
import java.io.IOException;
import java.util.UUID;
public final class ProfileByUsernameResponse extends Response {
public static void writeProfile(LaunchServer server, HOutput output, String username, String client, AuthProviderPair pair) throws IOException {
UUID uuid = pair.handler.usernameToUUID(username);
if (uuid == null) {
output.writeBoolean(false);
return;
}
// Write profile
output.writeBoolean(true);
ProfileByUUIDResponse.getProfile(server, uuid, username, client, pair.textureProvider).write(output);
}
public ProfileByUsernameResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws IOException {
String username = VerifyHelper.verifyUsername(input.readString(64));
debug("Username: " + username);
String client = input.readString(SerializeLimits.MAX_CLIENT);
// Write response
writeProfile(server, output, username, client, clientData.auth);
}
}

View file

@ -1,38 +0,0 @@
package ru.gravit.launchserver.response.update;
import ru.gravit.launcher.Launcher;
import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.utils.helper.LogHelper;
import java.io.IOException;
import java.util.Collection;
public final class ProfilesResponse extends Response {
public ProfilesResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws IOException {
// Resolve launcher binary
input.readBoolean();
if (clientData.type == Client.Type.USER && !clientData.checkSign) {
LogHelper.warning("User session: %d ip %s try get profiles", session, ip);
requestError("Access denied");
return;
}
writeNoError(output);
Collection<ClientProfile> profiles = server.getProfiles();
output.writeLength(profiles.size(), 0);
for (ClientProfile profile : profiles) {
LogHelper.debug("Writted profile: %s", profile.getTitle());
output.writeString(Launcher.gson.toJson(profile), 0);
}
}
}

View file

@ -1,28 +0,0 @@
package ru.gravit.launchserver.response.update;
import ru.gravit.launcher.hasher.HashedDir;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.response.Response;
import ru.gravit.launchserver.socket.Client;
import java.util.Map.Entry;
import java.util.Set;
public final class UpdateListResponse extends Response {
public UpdateListResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws Exception {
Set<Entry<String, SignedObjectHolder<HashedDir>>> updateDirs = server.getUpdateDirs();
// Write all update dirs names
output.writeLength(updateDirs.size(), 0);
for (Entry<String, SignedObjectHolder<HashedDir>> entry : updateDirs)
output.writeString(entry.getKey(), 255);
}
}

View file

@ -1,140 +0,0 @@
package ru.gravit.launchserver.response.update;
import ru.gravit.launcher.hasher.HashedDir;
import ru.gravit.launcher.hasher.HashedEntry;
import ru.gravit.launcher.hasher.HashedEntry.Type;
import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launcher.request.UpdateAction;
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.response.Response;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.utils.helper.IOHelper;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.Deque;
import java.util.LinkedList;
import java.util.zip.DeflaterOutputStream;
public final class UpdateResponse extends Response {
public UpdateResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
super(server, session, input, output, ip, clientData);
}
@Override
public void reply() throws IOException {
// Read update dir name
String updateDirName = IOHelper.verifyFileName(input.readString(255));
SignedObjectHolder<HashedDir> hdir = server.getUpdateDir(updateDirName);
if (hdir == null) {
requestError(String.format("Unknown update dir: %s", updateDirName));
return;
}
if (!clientData.isAuth || clientData.type != Client.Type.USER || clientData.profile == null) {
requestError("Access denied");
return;
}
if (!clientData.permissions.canAdmin) {
for (ClientProfile p : server.getProfiles()) {
if (!clientData.profile.getTitle().equals(p.getTitle())) continue;
if (!p.isWhitelistContains(clientData.username)) {
requestError("You don't download this folder");
return;
}
}
}
writeNoError(output);
// Write update hdir
debug("Update dir: '%s'", updateDirName);
hdir.write(output);
output.writeBoolean(server.config.compress);
output.flush();
// Prepare variables for actions queue
Path dir = server.updatesDir.resolve(updateDirName);
Deque<HashedDir> dirStack = new LinkedList<>();
dirStack.add(hdir.object);
// Perform update
// noinspection IOResourceOpenedButNotSafelyClosed
OutputStream fileOutput = server.config.compress ? new DeflaterOutputStream(output.stream, IOHelper.newDeflater(), IOHelper.BUFFER_SIZE, true) : output.stream;
UpdateAction[] actionsSlice = new UpdateAction[SerializeLimits.MAX_QUEUE_SIZE];
loop:
while (true) {
// Read actions slice
int length = input.readLength(actionsSlice.length);
for (int i = 0; i < length; i++)
actionsSlice[i] = new UpdateAction(input);
// Perform actions
for (int i = 0; i < length; i++) {
UpdateAction action = actionsSlice[i];
switch (action.type) {
case CD:
debug("CD '%s'", action.name);
// Get hashed dir (for validation)
HashedEntry hSubdir = dirStack.getLast().getEntry(action.name);
if (hSubdir == null || hSubdir.getType() != Type.DIR)
throw new IOException("Unknown hashed dir: " + action.name);
dirStack.add((HashedDir) hSubdir);
// Resolve dir
dir = dir.resolve(action.name);
break;
case GET:
debug("GET '%s'", action.name);
// Get hashed file (for validation)
HashedEntry hFile = dirStack.getLast().getEntry(action.name);
if (hFile == null || hFile.getType() != Type.FILE)
throw new IOException("Unknown hashed file: " + action.name);
// Resolve and write file
Path file = dir.resolve(action.name);
if (IOHelper.readAttributes(file).size() != hFile.size()) {
fileOutput.write(0x0);
fileOutput.flush();
throw new IOException("Unknown hashed file: " + action.name);
}
fileOutput.write(0xFF);
try (InputStream fileInput = IOHelper.newInput(file)) {
IOHelper.transfer(fileInput, fileOutput);
}
break;
case CD_BACK:
debug("CD ..");
// Remove from hashed dir stack
dirStack.removeLast();
if (dirStack.isEmpty())
throw new IOException("Empty hDir stack");
// Get parent
dir = dir.getParent();
break;
case FINISH:
break loop;
default:
throw new AssertionError(String.format("Unsupported action type: '%s'", action.type.name()));
}
}
// Flush all actions
fileOutput.flush();
}
// So we've updated :)
if (fileOutput instanceof DeflaterOutputStream)
((DeflaterOutputStream) fileOutput).finish();
}
}

View file

@ -11,10 +11,10 @@
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.profile.ProfileByUUIDResponse;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService;
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
import ru.gravit.launchserver.socket.websocket.json.profile.ProfileByUUIDResponse;
import ru.gravit.utils.helper.IOHelper;
import ru.gravit.utils.helper.LogHelper;
import ru.gravit.utils.helper.SecurityHelper;
@ -84,7 +84,7 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
AuthProviderPair pair;
if (auth_id.isEmpty()) pair = LaunchServer.server.config.getAuthProviderPair();
else pair = LaunchServer.server.config.getAuthProviderPair(auth_id);
ru.gravit.launchserver.response.auth.AuthResponse.AuthContext context = new ru.gravit.launchserver.response.auth.AuthResponse.AuthContext(0, login, password.length(), customText, client, ip, null, false);
AuthContext context = new AuthContext(0, login, password.length(), customText, client, ip, null, false);
AuthProvider provider = pair.provider;
LaunchServer.server.authHookManager.preHook(context, clientData);
provider.preAuth(login, password, customText, ip);
@ -128,5 +128,25 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
service.sendObject(ctx, new ErrorRequestEvent(e.getMessage()));
}
}
public static class AuthContext {
public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, String ip, boolean isServerAuth) {
this.session = session;
this.login = login;
this.password_lenght = password_lenght;
this.customText = customText;
this.client = client;
this.hwid = hwid;
this.ip = ip;
this.isServerAuth = isServerAuth;
}
public long session;
public String login;
public int password_lenght; //Use AuthProvider for get password
public String client;
public String hwid;
public String customText;
public String ip;
public boolean isServerAuth;
}
}

View file

@ -5,10 +5,10 @@
import ru.gravit.launcher.events.request.ErrorRequestEvent;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
import ru.gravit.launchserver.socket.Client;
import ru.gravit.launchserver.socket.websocket.WebSocketService;
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
import ru.gravit.launchserver.socket.websocket.json.profile.ProfileByUUIDResponse;
import ru.gravit.utils.helper.LogHelper;
public class CheckServerResponse implements JsonResponseInterface {

View file

@ -1,8 +1,6 @@
package ru.gravit.launchserver.console;
import ru.gravit.launcher.request.admin.ExecCommandRequest;
import ru.gravit.utils.command.JLineCommandHandler;
import ru.gravit.utils.helper.LogHelper;
import java.io.IOException;
@ -13,11 +11,5 @@ public RemoteJLineCommandHandler() throws IOException {
@Override
public void eval(String line, boolean bell) {
if (line.equals("exit")) System.exit(0);
ExecCommandRequest request = new ExecCommandRequest(System.out::println, line);
try {
request.request();
} catch (Exception e) {
LogHelper.error(e);
}
}
}

View file

@ -1,8 +1,6 @@
package ru.gravit.launchserver.console;
import ru.gravit.launcher.request.admin.ExecCommandRequest;
import ru.gravit.utils.command.StdCommandHandler;
import ru.gravit.utils.helper.LogHelper;
public class RemoteStdCommandHandler extends StdCommandHandler {
public RemoteStdCommandHandler(boolean readCommands) {
@ -12,11 +10,5 @@ public RemoteStdCommandHandler(boolean readCommands) {
@Override
public void eval(String line, boolean bell) {
if (line.equals("exit")) System.exit(0);
ExecCommandRequest request = new ExecCommandRequest(System.out::println, line);
try {
request.request();
} catch (Exception e) {
LogHelper.error(e);
}
}
}

View file

@ -63,7 +63,6 @@ public static void addLauncherClassBindings(Map<String, Object> bindings) {
bindings.put("RequestClass", Request.class);
bindings.put("RequestTypeClass", RequestType.class);
bindings.put("RequestExceptionClass", RequestException.class);
bindings.put("CustomRequestClass", CustomRequest.class);
bindings.put("PingRequestClass", PingRequest.class);
bindings.put("AuthRequestClass", AuthRequest.class);
bindings.put("JoinServerRequestClass", JoinServerRequest.class);

View file

@ -1,39 +0,0 @@
package ru.gravit.launcher.request;
import ru.gravit.launcher.LauncherAPI;
import ru.gravit.launcher.LauncherConfig;
import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.utils.helper.VerifyHelper;
public abstract class CustomRequest<T> extends Request<T> {
@LauncherAPI
public CustomRequest() {
this(null);
}
@LauncherAPI
public CustomRequest(LauncherConfig config) {
super(config);
}
@LauncherAPI
public abstract String getName();
@Override
public final Integer getLegacyType() {
return 255;
}
@Override
protected final T requestDo(HInput input, HOutput output) throws Exception {
output.writeASCII(VerifyHelper.verifyIDName(getName()), 255);
output.flush();
// Custom request redirect
return requestDoCustom(input, output);
}
@LauncherAPI
protected abstract T requestDoCustom(HInput input, HOutput output);
}

View file

@ -19,17 +19,4 @@ public PingRequest() {
public PingRequest(LauncherConfig config) {
super(config);
}
@Override
public Integer getLegacyType() {
return RequestType.PING.getNumber();
}
@Override
protected Void requestDo(HInput input, HOutput output) throws IOException {
byte pong = (byte) input.readUnsignedByte();
if (pong != SerializeLimits.EXPECTED_BYTE)
throw new IOException("Illegal ping response: " + pong);
return null;
}
}

View file

@ -43,9 +43,6 @@ protected Request(LauncherConfig config) {
this.config = config == null ? Launcher.getConfig() : config;
}
@LauncherAPI
public abstract Integer getLegacyType();
@LauncherAPI
protected final void readError(HInput input) throws IOException {
String error = input.readString(0);
@ -57,39 +54,11 @@ protected final void readError(HInput input) throws IOException {
public R request() throws Exception {
if (!started.compareAndSet(false, true))
throw new IllegalStateException("Request already started");
R wsResult = null;
if (config.isNettyEnabled)
wsResult = requestWebSockets();
if (wsResult != null) return wsResult;
// Make request to LaunchServer
try (Socket socket = IOHelper.newSocket()) {
socket.connect(IOHelper.resolve(config.address));
try (HInput input = new HInput(socket.getInputStream());
HOutput output = new HOutput(socket.getOutputStream())) {
writeHandshake(input, output);
return requestDo(input, output);
}
}
return requestWebSockets();
}
protected R requestWebSockets() throws Exception {
return null;
}
@LauncherAPI
protected abstract R requestDo(HInput input, HOutput output) throws Exception;
private void writeHandshake(HInput input, HOutput output) throws IOException {
// Write handshake
output.writeInt(Launcher.PROTOCOL_MAGIC);
output.writeBigInteger(config.publicKey.getModulus(), SecurityHelper.RSA_KEY_LENGTH + 1);
output.writeLong(session);
output.writeVarInt(getLegacyType());
output.flush();
// Verify is accepted
if (!input.readBoolean())
requestError("Serverside not accepted this connection");
}
}

View file

@ -1,39 +0,0 @@
package ru.gravit.launcher.request.admin;
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.LogHelper;
public class ExecCommandRequest extends Request<Boolean> {
public LogHelper.Output loutput;
public String cmd;
public ExecCommandRequest(LogHelper.Output output, String cmd) {
this.loutput = output;
this.cmd = cmd;
}
@Override
public Integer getLegacyType() {
return RequestType.EXECCOMMAND.getNumber();
}
@Override
protected Boolean requestDo(HInput input, HOutput output) throws Exception {
readError(input);
output.writeString(cmd, SerializeLimits.MAX_COMMAND);
boolean isContinue = true;
while (isContinue) {
isContinue = input.readBoolean();
if (isContinue) {
String log = input.readString(SerializeLimits.MAX_COMMAND);
if (loutput != null) loutput.println(log);
}
}
readError(input);
return true;
}
}

View file

@ -96,53 +96,6 @@ public AuthRequest(String login, byte[] password, HWID hwid, String auth_id) {
this(null, login, password, hwid, auth_id);
}
@Override
public Integer getLegacyType() {
return RequestType.AUTH.getNumber();
}
/*public class EchoRequest implements RequestInterface
{
String echo;
public EchoRequest(String echo) {
this.echo = echo;
}
@Override
public String getLegacyType() {
return "echo";
}
}*/
@Override
protected AuthRequestEvent requestDo(HInput input, HOutput output) throws IOException {
/*try {
LegacyRequestBridge.sendRequest(new EchoRequest("Hello World!"));
} catch (InterruptedException e) {
e.printStackTrace();
}*/
output.writeString(login, SerializeLimits.MAX_LOGIN);
output.writeBoolean(Launcher.profile != null);
if (Launcher.profile != null)
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
output.writeString(auth_id, SerializeLimits.MAX_QUEUE_SIZE);
output.writeString(hwid.getSerializeString(), 0);
//output.writeLong(0);
//output.writeLong(0);
//output.writeLong(0);
output.writeByteArray(encryptedPassword, SecurityHelper.CRYPTO_MAX_LENGTH);
output.writeString(customText, SerializeLimits.MAX_CUSTOM_TEXT);
output.flush();
// Read UUID and access token
readError(input);
PlayerProfile pp = new PlayerProfile(input);
String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH);
ClientPermissions permissions = new ClientPermissions(input);
String protectToken = input.readString(SerializeLimits.MAX_CUSTOM_TEXT);
return new AuthRequestEvent(permissions, pp, accessToken, protectToken);
}
@Override
public String getType() {
return "auth";

View file

@ -1,93 +0,0 @@
package ru.gravit.launcher.request.auth;
import ru.gravit.launcher.ClientPermissions;
import ru.gravit.launcher.LauncherAPI;
import ru.gravit.launcher.LauncherConfig;
import ru.gravit.launcher.LauncherNetworkAPI;
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.SecurityHelper;
import ru.gravit.utils.helper.VerifyHelper;
import java.io.IOException;
public final class AuthServerRequest extends Request<ClientPermissions> {
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;
}
}
@LauncherNetworkAPI
private final String login;
@LauncherNetworkAPI
private final byte[] encryptedPassword;
@LauncherNetworkAPI
private final String auth_id;
@LauncherNetworkAPI
private final String title;
@LauncherAPI
public AuthServerRequest(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 = "";
title = "";
}
@LauncherAPI
public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPassword, String 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;
title = "";
}
@LauncherAPI
public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPassword, String auth_id, String title) {
super(config);
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
this.encryptedPassword = encryptedPassword.clone();
this.auth_id = auth_id;
this.title = title;
}
@LauncherAPI
public AuthServerRequest(String login, byte[] encryptedPassword) {
this(null, login, encryptedPassword);
}
@LauncherAPI
public AuthServerRequest(String login, byte[] encryptedPassword, String auth_id) {
this(null, login, encryptedPassword, auth_id);
}
@Override
public Integer getLegacyType() {
return RequestType.SERVERAUTH.getNumber();
}
@Override
protected ClientPermissions requestDo(HInput input, HOutput output) throws IOException {
output.writeString(login, SerializeLimits.MAX_LOGIN);
output.writeString(title, SerializeLimits.MAX_CLIENT);
output.writeString(auth_id, SerializeLimits.MAX_QUEUE_SIZE);
output.writeByteArray(encryptedPassword, SecurityHelper.CRYPTO_MAX_LENGTH);
output.flush();
// Read UUID and access token
readError(input);
return new ClientPermissions(input);
}
}

View file

@ -1,41 +0,0 @@
package ru.gravit.launcher.request.auth;
import ru.gravit.launcher.Launcher;
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 java.net.InetSocketAddress;
public class ChangeServerRequest extends Request<ChangeServerRequest.Result> {
@Override
public Integer getLegacyType() {
return RequestType.CHANGESERVER.getNumber();
}
public boolean change(Result result) {
if (!result.needChange) return false;
Launcher.getConfig().address = InetSocketAddress.createUnresolved(result.address, result.port);
return true;
}
@Override
protected Result requestDo(HInput input, HOutput output) throws Exception {
readError(input);
Result result = new Result();
result.needChange = input.readBoolean();
if (result.needChange) {
result.address = input.readString(255);
result.port = input.readInt();
}
if (result.needChange) change(result);
return result;
}
public class Result {
public boolean needChange;
public String address;
public int port;
}
}

View file

@ -43,27 +43,6 @@ public CheckServerRequestEvent requestWebSockets() throws Exception
return (CheckServerRequestEvent) LegacyRequestBridge.sendRequest(this);
}
@Override
public Integer getLegacyType() {
return RequestType.CHECK_SERVER.getNumber();
}
@Override
protected CheckServerRequestEvent requestDo(HInput input, HOutput output) throws IOException {
output.writeString(username, SerializeLimits.MAX_LOGIN);
output.writeASCII(serverID, SerializeLimits.MAX_SERVERID); // 1 char for minus sign
if (Launcher.profile == null) {
LogHelper.error("Profile is null. Title is not net.");
output.writeString("", SerializeLimits.MAX_CLIENT);
} else
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
output.flush();
// Read response
readError(input);
return input.readBoolean() ? new CheckServerRequestEvent(new PlayerProfile(input)) : null;
}
@Override
public String getType() {
return "checkServer";

View file

@ -43,24 +43,6 @@ public JoinServerRequestEvent requestWebSockets() throws IOException, Interrupte
public JoinServerRequest(String username, String accessToken, String serverID) {
this(null, username, accessToken, serverID);
}
@Override
public Integer getLegacyType() {
return RequestType.JOIN_SERVER.getNumber();
}
@Override
protected JoinServerRequestEvent requestDo(HInput input, HOutput output) throws IOException {
output.writeString(username, SerializeLimits.MAX_LOGIN);
output.writeASCII(accessToken, -SecurityHelper.TOKEN_STRING_LENGTH);
output.writeASCII(serverID, SerializeLimits.MAX_SERVERID); // 1 char for minus sign
output.flush();
// Read response
readError(input);
return new JoinServerRequestEvent(input.readBoolean());
}
@Override
public String getType() {
return "joinServer";

View file

@ -23,16 +23,6 @@ public RestoreSessionRequestEvent requestWebSockets() throws IOException, Interr
return (RestoreSessionRequestEvent) LegacyRequestBridge.sendRequest(this);
}
@Override
public Integer getLegacyType() {
return 0;
}
@Override
protected RestoreSessionRequestEvent requestDo(HInput input, HOutput output) throws Exception {
return new RestoreSessionRequestEvent();
}
@Override
public String getType() {
return "restoreSession";

View file

@ -28,18 +28,6 @@ public SetProfileRequestEvent requestWebSockets() throws Exception {
return (SetProfileRequestEvent) LegacyRequestBridge.sendRequest(this);
}
@Override
public Integer getLegacyType() {
return RequestType.SETPROFILE.getNumber();
}
@Override
protected SetProfileRequestEvent requestDo(HInput input, HOutput output) throws Exception {
output.writeString(profile.getTitle(), SerializeLimits.MAX_CLIENT);
readError(input);
return new SetProfileRequestEvent(profile);
}
@Override
public String getType() {
return "setProfile";

View file

@ -93,30 +93,6 @@ public LauncherRequest(LauncherConfig config) {
}
}
@Override
public Integer getLegacyType() {
return RequestType.LAUNCHER.getNumber();
}
@Override
protected LauncherRequestEvent requestDo(HInput input, HOutput output) throws Exception {
output.writeBoolean(EXE_BINARY);
output.writeByteArray(digest, 0);
output.flush();
readError(input);
// Verify launcher sign
boolean shouldUpdate = input.readBoolean();
if (shouldUpdate) {
byte[] binary = input.readByteArray(0);
LauncherRequestEvent result = new LauncherRequestEvent(binary, digest);
update(Launcher.getConfig(), result);
}
// Return request result
return new LauncherRequestEvent(null, digest);
}
@Override
public String getType() {
return "launcher";

View file

@ -84,41 +84,4 @@ public LegacyLauncherRequest() {
public LegacyLauncherRequest(LauncherConfig config) {
super(config);
}
@Override
public Integer getLegacyType() {
return RequestType.LEGACYLAUNCHER.getNumber();
}
@Override
protected Result requestDo(HInput input, HOutput output) throws Exception {
output.writeBoolean(EXE_BINARY);
output.flush();
readError(input);
// Verify launcher sign
RSAPublicKey publicKey = config.publicKey;
byte[] sign = input.readByteArray(-SecurityHelper.RSA_KEY_LENGTH);
boolean shouldUpdate = !SecurityHelper.isValidSign(BINARY_PATH, sign, publicKey);
// Update launcher if need
output.writeBoolean(shouldUpdate);
output.flush();
if (shouldUpdate) {
byte[] binary = input.readByteArray(0);
SecurityHelper.verifySign(binary, sign, config.publicKey);
return new Result(binary, sign, Collections.emptyList());
}
// Read clients profiles list
int count = input.readLength(0);
List<ClientProfile> profiles = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
String prof = input.readString(0);
profiles.add(Launcher.gson.fromJson(prof, ClientProfile.class));
}
// Return request result
return new Result(null, sign, profiles);
}
}

View file

@ -27,32 +27,11 @@ public ProfilesRequest(LauncherConfig config) {
super(config);
}
@Override
public Integer getLegacyType() {
return RequestType.PROFILES.getNumber();
}
@Override
public ProfilesRequestEvent requestWebSockets() throws Exception {
return (ProfilesRequestEvent) LegacyRequestBridge.sendRequest(this);
}
@Override
protected ProfilesRequestEvent requestDo(HInput input, HOutput output) throws Exception {
output.writeBoolean(true);
output.flush();
readError(input);
int count = input.readLength(0);
List<ClientProfile> profiles = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
String prof = input.readString(0);
profiles.add(Launcher.gson.fromJson(prof, ClientProfile.class));
}
// Return request result
return new ProfilesRequestEvent(profiles);
}
@Override
public String getType() {
return "profiles";

View file

@ -30,24 +30,6 @@ public UpdateListRequestEvent requestWebSockets() throws Exception {
return (UpdateListRequestEvent) LegacyRequestBridge.sendRequest(this);
}
@Override
public Integer getLegacyType() {
return RequestType.UPDATE_LIST.getNumber();
}
@Override
protected UpdateListRequestEvent requestDo(HInput input, HOutput output) throws IOException {
int count = input.readLength(0);
// Read all update dirs names
HashSet<String> result = new HashSet<>(count);
for (int i = 0; i < count; i++)
result.add(IOHelper.verifyFileName(input.readString(255)));
// We're done. Make it unmodifiable and return
return new UpdateListRequestEvent(result);
}
@Override
public String getType() {
return "updateList";

View file

@ -284,48 +284,6 @@ private void deleteExtraDir(Path subDir, HashedDir subHDir, boolean flag) throws
}
}
private void downloadFile(Path file, HashedFile hFile, InputStream input) throws IOException {
String filePath = IOHelper.toString(dir.relativize(file));
updateState(filePath, 0L, hFile.size);
// Start file update
MessageDigest digest = this.digest ? SecurityHelper.newDigest(DigestAlgorithm.MD5) : null;
try (OutputStream fileOutput = IOHelper.newOutput(file)) {
long downloaded = 0L;
// Download with digest update
byte[] bytes = IOHelper.newBuffer();
while (downloaded < hFile.size) {
int remaining = (int) Math.min(hFile.size - downloaded, bytes.length);
int length = input.read(bytes, 0, remaining);
if (length < 0)
throw new EOFException(String.format("%d bytes remaining", hFile.size - downloaded));
// Update file
fileOutput.write(bytes, 0, length);
if (digest != null)
digest.update(bytes, 0, length);
// Update state
downloaded += length;
totalDownloaded += length;
updateState(filePath, downloaded, hFile.size);
}
}
// Verify digest
if (digest != null) {
byte[] digestBytes = digest.digest();
if (!hFile.isSameDigest(digestBytes))
throw new SecurityException(String.format("File digest mismatch: '%s'", filePath));
}
}
@Override
public Integer getLegacyType() {
return RequestType.UPDATE.getNumber();
}
@Override
public UpdateRequestEvent request() throws Exception {
Files.createDirectories(dir);
@ -335,76 +293,6 @@ public UpdateRequestEvent request() throws Exception {
return super.request();
}
@Override
protected UpdateRequestEvent requestDo(HInput input, HOutput output) throws IOException, SignatureException {
// Write update dir name
output.writeString(dirName, 255);
output.flush();
readError(input);
// Get diff between local and remote dir
SignedObjectHolder<HashedDir> remoteHDirHolder = new SignedObjectHolder<>(input, config.publicKey, HashedDir::new);
HashedDir hackHackedDir = remoteHDirHolder.object;
Launcher.profile.pushOptionalFile(hackHackedDir, !Launcher.profile.isUpdateFastCheck());
HashedDir.Diff diff = hackHackedDir.diff(localDir, matcher);
totalSize = diff.mismatch.size();
boolean compress = input.readBoolean();
// Build actions queue
Queue<UpdateAction> queue = new LinkedList<>();
fillActionsQueue(queue, diff.mismatch);
queue.add(UpdateAction.FINISH);
// noinspection IOResourceOpenedButNotSafelyClosed
InputStream fileInput = compress ? new InflaterInputStream(input.stream, IOHelper.newInflater(), IOHelper.BUFFER_SIZE) : input.stream;
// Download missing first
// (otherwise it will cause mustdie indexing bug)
startTime = Instant.now();
Path currentDir = dir;
UpdateAction[] actionsSlice = new UpdateAction[SerializeLimits.MAX_QUEUE_SIZE];
while (!queue.isEmpty()) {
int length = Math.min(queue.size(), SerializeLimits.MAX_QUEUE_SIZE);
// Write actions slice
output.writeLength(length, SerializeLimits.MAX_QUEUE_SIZE);
for (int i = 0; i < length; i++) {
UpdateAction action = queue.remove();
actionsSlice[i] = action;
action.write(output);
}
output.flush();
// Perform actions
for (int i = 0; i < length; i++) {
UpdateAction action = actionsSlice[i];
switch (action.type) {
case CD:
currentDir = currentDir.resolve(action.name);
Files.createDirectories(currentDir);
break;
case GET:
Path targetFile = currentDir.resolve(action.name);
if (fileInput.read() != 0xFF)
throw new IOException("Serverside cached size mismath for file " + action.name);
downloadFile(targetFile, (HashedFile) action.entry, fileInput);
break;
case CD_BACK:
currentDir = currentDir.getParent();
break;
case FINISH:
break;
default:
throw new AssertionError(String.format("Unsupported action type: '%s'", action.type.name()));
}
}
}
// Write update completed packet
deleteExtraDir(dir, diff.extra, diff.extra.flag);
return new UpdateRequestEvent(remoteHDirHolder.object);
}
@LauncherAPI
public void setStateCallback(Callback callback) {
stateCallback = callback;

View file

@ -50,29 +50,6 @@ public BatchProfileByUsernameRequestEvent requestWebSockets() throws IOException
return (BatchProfileByUsernameRequestEvent) LegacyRequestBridge.sendRequest(this);
}
@Override
public Integer getLegacyType() {
return RequestType.BATCH_PROFILE_BY_USERNAME.getNumber();
}
@Override
protected BatchProfileByUsernameRequestEvent requestDo(HInput input, HOutput output) throws IOException {
output.writeLength(list.length, SerializeLimits.MAX_BATCH_SIZE);
for (Entry username : list) {
output.writeString(username.username, SerializeLimits.MAX_LOGIN);
output.writeString(username.client, SerializeLimits.MAX_CLIENT);
}
output.flush();
// Read profiles response
PlayerProfile[] profiles = new PlayerProfile[list.length];
for (int i = 0; i < profiles.length; i++)
profiles[i] = input.readBoolean() ? new PlayerProfile(input) : null;
// Return result
return new BatchProfileByUsernameRequestEvent(profiles);
}
@Override
public String getType() {
return "batchProfileByUsername";

View file

@ -38,21 +38,6 @@ public ProfileByUUIDRequestEvent requestWebSockets() throws IOException, Interru
return (ProfileByUUIDRequestEvent) LegacyRequestBridge.sendRequest(this);
}
@Override
public Integer getLegacyType() {
return RequestType.PROFILE_BY_UUID.getNumber();
}
@Override
protected ProfileByUUIDRequestEvent requestDo(HInput input, HOutput output) throws IOException {
output.writeUUID(uuid);
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
output.flush();
// Return profile
return input.readBoolean() ? new ProfileByUUIDRequestEvent(new PlayerProfile(input)) : null;
}
@Override
public String getType() {
return "profileByUUID";

View file

@ -37,20 +37,6 @@ public ProfileByUsernameRequestEvent requestWebSockets() throws IOException, Int
return (ProfileByUsernameRequestEvent) LegacyRequestBridge.sendRequest(this);
}
@Override
public Integer getLegacyType() {
return RequestType.PROFILE_BY_USERNAME.getNumber();
}
@Override
protected ProfileByUsernameRequestEvent requestDo(HInput input, HOutput output) throws IOException {
output.writeString(username, SerializeLimits.MAX_LOGIN);
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
output.flush();
// Return profile
return input.readBoolean() ? new ProfileByUsernameRequestEvent(new PlayerProfile(input)) : null;
}
@Override
public String getType() {
return "profileByUsername";

View file

@ -8,7 +8,6 @@
import ru.gravit.launcher.events.request.ProfilesRequestEvent;
import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launcher.request.auth.AuthRequest;
import ru.gravit.launcher.request.auth.AuthServerRequest;
import ru.gravit.launcher.request.update.ProfilesRequest;
import ru.gravit.launcher.request.websockets.LegacyRequestBridge;
import ru.gravit.launcher.server.setup.ServerWrapperSetup;
@ -53,13 +52,8 @@ public ServerWrapper(Type type, Path configPath) {
public boolean auth() {
try {
LauncherConfig cfg = Launcher.getConfig();
if(!config.websocket.enabled)
permissions = new AuthServerRequest(cfg, config.login, SecurityHelper.newRSAEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)), config.auth_id, config.title).request();
else
{
AuthRequest request = new AuthRequest(config.login, SecurityHelper.newRSAEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)), config.auth_id, AuthRequest.ConnectTypes.SERVER);
permissions = request.request().permissions;
}
AuthRequest request = new AuthRequest(config.login, SecurityHelper.newRSAEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)), config.auth_id, AuthRequest.ConnectTypes.SERVER);
permissions = request.request().permissions;
ProfilesRequestEvent result = new ProfilesRequest(cfg).request();
for (ClientProfile p : result.profiles) {
LogHelper.debug("Get profile: %s", p.getTitle());
@ -184,7 +178,7 @@ public void run(String... args) throws Throwable {
auth();
};
}
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s port %d. Title: %s", config.projectname, config.address, config.port, config.title);
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s port %d. Title: %s", config.projectname, config.websocket.address, config.title);
LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
LogHelper.info("Start Minecraft Server");
LogHelper.debug("Invoke main method %s", mainClass.getName());
@ -205,7 +199,7 @@ public void updateLauncherConfig() {
LauncherConfig cfg = null;
try {
cfg = new LauncherConfig(config.address, config.port, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname);
cfg = new LauncherConfig(config.websocket.address, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname);
if(config.websocket != null && config.websocket.enabled)
{
cfg.isNettyEnabled = true;
@ -235,8 +229,6 @@ public Config getDefaultConfig() {
Config newConfig = new Config();
newConfig.title = "Your profile title";
newConfig.projectname = "MineCraft";
newConfig.address = "localhost";
newConfig.port = 7240;
newConfig.login = "login";
newConfig.password = "password";
newConfig.mainclass = "";
@ -259,9 +251,7 @@ public void setConfig(Config config) {
public static final class Config {
public String title;
public String projectname;
public String address;
public WebSocketConf websocket;
public int port;
public int reconnectCount;
public int reconnectSleep;
public boolean customClassPath;

View file

@ -40,13 +40,10 @@ public void run() throws IOException {
return;
}
LogHelper.info("Found MainClass %s", mainClassName);
System.out.println("Print launchserver host:");
System.out.println("Print launchserver websocket host:");
String address = commands.commandHandler.readLine();
System.out.println("Print launchserver port:");
int port = Integer.valueOf(commands.commandHandler.readLine());
wrapper.config.mainclass = mainClassName;
wrapper.config.address = address;
wrapper.config.port = port;
wrapper.config.websocket.address = address;
if (!Files.exists(ServerWrapper.publicKeyFile)) {
LogHelper.error("public.key not found");
for (int i = 0; i < 10; ++i) {

View file

@ -7,7 +7,6 @@
import ru.gravit.utils.helper.VerifyHelper;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.*;
@ -21,8 +20,6 @@ public static AutogenConfig getAutogenConfig() {
}
// Instance
@LauncherAPI
public InetSocketAddress address;
public String nettyAddress;
public int nettyPort;
@LauncherAPI
@ -46,7 +43,6 @@ public static AutogenConfig getAutogenConfig() {
@LauncherAPI
public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException {
address = InetSocketAddress.createUnresolved(config.address, config.port);
publicKey = SecurityHelper.toPublicRSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
projectname = config.projectname;
clientPort = config.clientPort;
@ -80,8 +76,8 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException
}
@LauncherAPI
public LauncherConfig(String address, int port, RSAPublicKey publicKey, Map<String, byte[]> runtime, String projectname) {
this.address = InetSocketAddress.createUnresolved(address, port);
public LauncherConfig(String address, RSAPublicKey publicKey, Map<String, byte[]> runtime, String projectname) {
this.nettyAddress = address;
this.publicKey = Objects.requireNonNull(publicKey, "publicKey");
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
this.projectname = projectname;
@ -96,8 +92,8 @@ public LauncherConfig(String address, int port, RSAPublicKey publicKey, Map<Stri
}
@LauncherAPI
public LauncherConfig(String address, int port, RSAPublicKey publicKey, Map<String, byte[]> runtime) {
this.address = InetSocketAddress.createUnresolved(address, port);
public LauncherConfig(String address, RSAPublicKey publicKey, Map<String, byte[]> runtime) {
this.nettyAddress = address;
this.publicKey = Objects.requireNonNull(publicKey, "publicKey");
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
this.projectname = "Minecraft";