mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 03:25:19 +01:00
Validate checksums of downloaded dependencies
This commit is contained in:
parent
bbb2897d20
commit
94b4e3d366
@ -129,6 +129,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
private DefaultsProvider defaultsProvider;
|
||||
private ChildPermissionProvider childPermissionProvider;
|
||||
private LocaleManager localeManager;
|
||||
private DependencyManager dependencyManager;
|
||||
private CachedStateManager cachedStateManager;
|
||||
private ContextManager<Player> contextManager;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
@ -153,7 +154,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
senderFactory = new BukkitSenderFactory(this);
|
||||
log = new SenderLogger(this, getConsoleSender());
|
||||
|
||||
DependencyManager.loadDependencies(this, Collections.singleton(Dependency.CAFFEINE));
|
||||
dependencyManager = new DependencyManager(this);
|
||||
dependencyManager.loadDependencies(Collections.singleton(Dependency.CAFFEINE));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -192,7 +194,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
configuration.init();
|
||||
|
||||
Set<StorageType> storageTypes = StorageFactory.getRequiredTypes(this, StorageType.H2);
|
||||
DependencyManager.loadStorageDependencies(this, storageTypes);
|
||||
dependencyManager.loadStorageDependencies(storageTypes);
|
||||
|
||||
// setup the Bukkit defaults hook
|
||||
defaultsProvider = new DefaultsProvider();
|
||||
|
@ -40,7 +40,6 @@ import me.lucko.luckperms.common.commands.abstraction.SubCommand;
|
||||
import me.lucko.luckperms.common.commands.impl.migration.MigrationUtils;
|
||||
import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.dependencies.DependencyManager;
|
||||
import me.lucko.luckperms.common.locale.CommandSpec;
|
||||
import me.lucko.luckperms.common.locale.LocaleManager;
|
||||
import me.lucko.luckperms.common.logging.ProgressLogger;
|
||||
@ -95,7 +94,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
|
||||
if (type == null || type != StorageType.MYSQL) {
|
||||
// We need to load the Hikari/MySQL stuff.
|
||||
DependencyManager.loadStorageDependencies(plugin, ImmutableSet.of(StorageType.MYSQL));
|
||||
plugin.getDependencyManager().loadStorageDependencies(ImmutableSet.of(StorageType.MYSQL));
|
||||
}
|
||||
|
||||
String address = args.get(0);
|
||||
|
@ -111,6 +111,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
private ApiProvider apiProvider;
|
||||
private Logger log;
|
||||
private LocaleManager localeManager;
|
||||
private DependencyManager dependencyManager;
|
||||
private CachedStateManager cachedStateManager;
|
||||
private ContextManager<ProxiedPlayer> contextManager;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
@ -129,7 +130,8 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
senderFactory = new BungeeSenderFactory(this);
|
||||
log = new SenderLogger(this, getConsoleSender());
|
||||
|
||||
DependencyManager.loadDependencies(this, Collections.singleton(Dependency.CAFFEINE));
|
||||
dependencyManager = new DependencyManager(this);
|
||||
dependencyManager.loadDependencies(Collections.singleton(Dependency.CAFFEINE));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -145,7 +147,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
configuration.init();
|
||||
|
||||
Set<StorageType> storageTypes = StorageFactory.getRequiredTypes(this, StorageType.H2);
|
||||
DependencyManager.loadStorageDependencies(this, storageTypes);
|
||||
dependencyManager.loadStorageDependencies(storageTypes);
|
||||
|
||||
// register events
|
||||
getProxy().getPluginManager().registerListener(this, new BungeeConnectionListener(this));
|
||||
|
@ -25,38 +25,150 @@
|
||||
|
||||
package me.lucko.luckperms.common.dependencies;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Dependency {
|
||||
|
||||
CAFFEINE("com.github.ben-manes.caffeine", "caffeine", "2.6.0"),
|
||||
MARIADB_DRIVER("org.mariadb.jdbc", "mariadb-java-client", "2.2.0"),
|
||||
MYSQL_DRIVER("mysql", "mysql-connector-java", "5.1.44"),
|
||||
POSTGRESQL_DRIVER("org.postgresql", "postgresql", "9.4.1212"),
|
||||
H2_DRIVER("com.h2database", "h2", "1.4.196"),
|
||||
SQLITE_DRIVER("org.xerial", "sqlite-jdbc", "3.21.0"),
|
||||
HIKARI("com.zaxxer", "HikariCP", "2.7.3"),
|
||||
SLF4J_SIMPLE("org.slf4j", "slf4j-simple", "1.7.25"),
|
||||
SLF4J_API("org.slf4j", "slf4j-api", "1.7.25"),
|
||||
MONGODB_DRIVER("org.mongodb", "mongo-java-driver", "3.5.0"),
|
||||
JEDIS("https://github.com/lucko/jedis/releases/download/jedis-2.9.1-shaded/jedis-2.9.1-shaded.jar", "2.9.1-shaded"),
|
||||
CONFIGURATE_CORE("ninja.leaping.configurate", "configurate-core", "3.3"),
|
||||
CONFIGURATE_GSON("ninja.leaping.configurate", "configurate-gson", "3.3"),
|
||||
CONFIGURATE_YAML("ninja.leaping.configurate", "configurate-yaml", "3.3"),
|
||||
CONFIGURATE_HOCON("ninja.leaping.configurate", "configurate-hocon", "3.3"),
|
||||
HOCON_CONFIG("com.typesafe", "config", "1.3.1");
|
||||
|
||||
CAFFEINE(
|
||||
"com.github.ben-manes.caffeine",
|
||||
"caffeine",
|
||||
"2.6.0",
|
||||
"JmT16VQnCnVBAjRJCQkkkjmSVx2jajpzeBuKwpbzDA8="
|
||||
),
|
||||
MARIADB_DRIVER(
|
||||
"org.mariadb.jdbc",
|
||||
"mariadb-java-client",
|
||||
"2.2.0",
|
||||
"/q0LPGHrp3L9rvKr7TuA6urbtXBqvXis92mP4KhxzUw="
|
||||
),
|
||||
MYSQL_DRIVER(
|
||||
"mysql",
|
||||
"mysql-connector-java",
|
||||
"5.1.44",
|
||||
"d4RZVzTeWpoHBPB/tQP3mSafNy7L9MDUSOt4Ku9LGCc="
|
||||
),
|
||||
POSTGRESQL_DRIVER(
|
||||
"org.postgresql",
|
||||
"postgresql",
|
||||
"9.4.1212",
|
||||
"DLKhWL4xrPIY4KThjI89usaKO8NIBkaHc/xECUsMNl0="
|
||||
),
|
||||
H2_DRIVER(
|
||||
"com.h2database",
|
||||
"h2",
|
||||
"1.4.196",
|
||||
"CgX0oNW4WEAUiq3OY6QjtdPDbvRHVjibT6rQjScz+vU="
|
||||
),
|
||||
SQLITE_DRIVER(
|
||||
"org.xerial",
|
||||
"sqlite-jdbc",
|
||||
"3.21.0",
|
||||
"bglRaH4Y+vQFZV7TfOdsVLO3rJpauJ+IwjuRULAb45Y="
|
||||
),
|
||||
HIKARI(
|
||||
"com.zaxxer",
|
||||
"HikariCP",
|
||||
"2.7.4",
|
||||
"y9JE6/VmbydCqlV1z468+oqdkBswBk6aw+ECT178AT4="
|
||||
),
|
||||
SLF4J_SIMPLE(
|
||||
"org.slf4j",
|
||||
"slf4j-simple",
|
||||
"1.7.25",
|
||||
"CWbob/+lvlLT2ee4ndZ02YoD7tCkVPuvfBvZSTvZ2HQ="
|
||||
),
|
||||
SLF4J_API(
|
||||
"org.slf4j",
|
||||
"slf4j-api",
|
||||
"1.7.25",
|
||||
"GMSgCV1cHaa4F1kudnuyPSndL1YK1033X/OWHb3iW3k="
|
||||
),
|
||||
MONGODB_DRIVER(
|
||||
"org.mongodb",
|
||||
"mongo-java-driver",
|
||||
"3.5.0",
|
||||
"gxrbKVSI/xM6r+6uL7g7I0DzNV+hlNTtfw4UL13XdK8="
|
||||
),
|
||||
JEDIS(
|
||||
"https://github.com/lucko/jedis/releases/download/jedis-2.9.1-shaded/jedis-2.9.1-shaded.jar",
|
||||
"2.9.1-shaded",
|
||||
"mM19X6LyD97KP4RSbcCR5BTRAwQ0x9y02voX7ePOSjE="
|
||||
),
|
||||
CONFIGURATE_CORE(
|
||||
"ninja.leaping.configurate",
|
||||
"configurate-core",
|
||||
"3.3",
|
||||
"4leBJEqj1kVszaifZeKNl4hgHxG5M+Nk5TJKkPW2s4Y="
|
||||
),
|
||||
CONFIGURATE_GSON(
|
||||
"ninja.leaping.configurate",
|
||||
"configurate-gson",
|
||||
"3.3",
|
||||
"4HxrW3/ZKdn095x/W4gylQMNskdmteXYVxVv0UKGJA4="
|
||||
),
|
||||
CONFIGURATE_YAML(
|
||||
"ninja.leaping.configurate",
|
||||
"configurate-yaml",
|
||||
"3.3",
|
||||
"hgADp3g+xHHPD34bAuxMWtB+OQ718Tlw69jVp2KPJNk="
|
||||
),
|
||||
CONFIGURATE_HOCON(
|
||||
"ninja.leaping.configurate",
|
||||
"configurate-hocon",
|
||||
"3.3",
|
||||
"UIy5FVmsBUG6+Z1mpIEE2EXgtOI1ZL0p/eEW+BbtGLU="
|
||||
),
|
||||
HOCON_CONFIG(
|
||||
"com.typesafe",
|
||||
"config",
|
||||
"1.3.1",
|
||||
"5vrfxhCCINOmuGqn5OFsnnu4V7pYlViGMIuxOXImSvA="
|
||||
);
|
||||
|
||||
private final String url;
|
||||
private final String version;
|
||||
private final byte[] checksum;
|
||||
|
||||
private static final String MAVEN_CENTRAL_FORMAT = "https://repo1.maven.org/maven2/%s/%s/%s/%s-%s.jar";
|
||||
|
||||
Dependency(String groupId, String artifactId, String version) {
|
||||
this(String.format(MAVEN_CENTRAL_FORMAT, groupId.replace(".", "/"), artifactId, version, artifactId, version), version);
|
||||
Dependency(String groupId, String artifactId, String version, String checksum) {
|
||||
this(String.format(MAVEN_CENTRAL_FORMAT, groupId.replace(".", "/"), artifactId, version, artifactId, version), version, checksum);
|
||||
}
|
||||
|
||||
Dependency(String url, String version, String checksum) {
|
||||
this.url = url;
|
||||
this.version = version;
|
||||
this.checksum = Base64.getDecoder().decode(checksum);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
|
||||
for (Dependency dependency : values()) {
|
||||
URL url = new URL(dependency.getUrl());
|
||||
try (InputStream in = url.openStream()) {
|
||||
byte[] bytes = ByteStreams.toByteArray(in);
|
||||
if (bytes.length == 0) {
|
||||
throw new RuntimeException("Empty stream");
|
||||
}
|
||||
|
||||
byte[] hash = digest.digest(bytes);
|
||||
|
||||
if (Arrays.equals(hash, dependency.getChecksum())) {
|
||||
System.out.println("MATCH " + dependency.name() + ": " + Base64.getEncoder().encodeToString(hash));
|
||||
} else {
|
||||
System.out.println("NO MATCH " + dependency.name() + ": " + Base64.getEncoder().encodeToString(hash));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,9 @@
|
||||
|
||||
package me.lucko.luckperms.common.dependencies;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import me.lucko.luckperms.api.platform.PlatformType;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
@ -43,7 +42,10 @@ import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -52,17 +54,16 @@ import java.util.Set;
|
||||
/**
|
||||
* Responsible for loading runtime dependencies.
|
||||
*/
|
||||
@UtilityClass
|
||||
public class DependencyManager {
|
||||
private static final Method ADD_URL_METHOD;
|
||||
|
||||
static {
|
||||
Method addUrlMethod = null;
|
||||
Method addUrlMethod;
|
||||
try {
|
||||
addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||
addUrlMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
ADD_URL_METHOD = addUrlMethod;
|
||||
}
|
||||
@ -79,7 +80,19 @@ public class DependencyManager {
|
||||
.put(StorageType.H2, ImmutableList.of(Dependency.H2_DRIVER))
|
||||
.build();
|
||||
|
||||
public static void loadStorageDependencies(LuckPermsPlugin plugin, Set<StorageType> storageTypes) {
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final MessageDigest digest;
|
||||
|
||||
public DependencyManager(LuckPermsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
try {
|
||||
this.digest = MessageDigest.getInstance("SHA-1");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadStorageDependencies(Set<StorageType> storageTypes) {
|
||||
Set<Dependency> dependencies = new LinkedHashSet<>();
|
||||
for (StorageType storageType : storageTypes) {
|
||||
dependencies.addAll(STORAGE_DEPENDENCIES.get(storageType));
|
||||
@ -104,10 +117,10 @@ public class DependencyManager {
|
||||
dependencies.remove(Dependency.HOCON_CONFIG);
|
||||
}
|
||||
|
||||
loadDependencies(plugin, dependencies);
|
||||
loadDependencies(dependencies);
|
||||
}
|
||||
|
||||
public static void loadDependencies(LuckPermsPlugin plugin, Set<Dependency> dependencies) {
|
||||
public void loadDependencies(Set<Dependency> dependencies) {
|
||||
plugin.getLog().info("Identified the following dependencies: " + dependencies.toString());
|
||||
|
||||
File libDir = new File(plugin.getDataDirectory(), "lib");
|
||||
@ -119,7 +132,7 @@ public class DependencyManager {
|
||||
List<File> filesToLoad = new ArrayList<>();
|
||||
for (Dependency dependency : dependencies) {
|
||||
try {
|
||||
filesToLoad.add(downloadDependency(plugin, libDir, dependency));
|
||||
filesToLoad.add(downloadDependency(libDir, dependency));
|
||||
} catch (Throwable e) {
|
||||
plugin.getLog().severe("Exception whilst downloading dependency " + dependency.name());
|
||||
e.printStackTrace();
|
||||
@ -129,7 +142,7 @@ public class DependencyManager {
|
||||
// Load classes.
|
||||
for (File file : filesToLoad) {
|
||||
try {
|
||||
loadJar(plugin, file);
|
||||
loadJar(file);
|
||||
} catch (Throwable t) {
|
||||
plugin.getLog().severe("Failed to load dependency jar " + file.getName());
|
||||
t.printStackTrace();
|
||||
@ -137,7 +150,7 @@ public class DependencyManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static File downloadDependency(LuckPermsPlugin plugin, File libDir, Dependency dependency) throws Exception {
|
||||
private File downloadDependency(File libDir, Dependency dependency) throws Exception {
|
||||
String fileName = dependency.name().toLowerCase() + "-" + dependency.getVersion() + ".jar";
|
||||
|
||||
File file = new File(libDir, fileName);
|
||||
@ -149,7 +162,17 @@ public class DependencyManager {
|
||||
|
||||
plugin.getLog().info("Dependency '" + fileName + "' could not be found. Attempting to download.");
|
||||
try (InputStream in = url.openStream()) {
|
||||
Files.copy(in, file.toPath());
|
||||
byte[] bytes = ByteStreams.toByteArray(in);
|
||||
if (bytes.length == 0) {
|
||||
throw new RuntimeException("Empty stream");
|
||||
}
|
||||
|
||||
byte[] hash = this.digest.digest(bytes);
|
||||
if (!Arrays.equals(hash, dependency.getChecksum())) {
|
||||
throw new RuntimeException("Downloaded file had an invalid hash.");
|
||||
}
|
||||
|
||||
Files.write(file.toPath(), bytes);
|
||||
}
|
||||
|
||||
if (!file.exists()) {
|
||||
@ -160,7 +183,7 @@ public class DependencyManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadJar(LuckPermsPlugin plugin, File file) {
|
||||
private void loadJar(File file) {
|
||||
// get the classloader to load into
|
||||
ClassLoader classLoader = plugin.getClass().getClassLoader();
|
||||
|
||||
|
@ -38,6 +38,7 @@ import me.lucko.luckperms.common.commands.sender.Sender;
|
||||
import me.lucko.luckperms.common.commands.utils.CommandUtils;
|
||||
import me.lucko.luckperms.common.config.LuckPermsConfiguration;
|
||||
import me.lucko.luckperms.common.contexts.ContextManager;
|
||||
import me.lucko.luckperms.common.dependencies.DependencyManager;
|
||||
import me.lucko.luckperms.common.locale.LocaleManager;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.logging.Logger;
|
||||
@ -146,6 +147,13 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
LocaleManager getLocaleManager();
|
||||
|
||||
/**
|
||||
* Gets the dependency manager for the plugin
|
||||
*
|
||||
* @return the dependency manager
|
||||
*/
|
||||
DependencyManager getDependencyManager();
|
||||
|
||||
/**
|
||||
* Gets the context manager.
|
||||
* This object handles context accumulation for all players on the platform.
|
||||
|
@ -178,6 +178,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
private me.lucko.luckperms.common.logging.Logger log;
|
||||
private LuckPermsService service;
|
||||
private LocaleManager localeManager;
|
||||
private DependencyManager dependencyManager;
|
||||
private CachedStateManager cachedStateManager;
|
||||
private ContextManager<Subject> contextManager;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
@ -195,6 +196,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
localeManager = new NoopLocaleManager();
|
||||
senderFactory = new SpongeSenderFactory(this);
|
||||
log = new SenderLogger(this, getConsoleSender());
|
||||
dependencyManager = new DependencyManager(this);
|
||||
|
||||
LuckPermsPlugin.sendStartupBanner(getConsoleSender(), this);
|
||||
verboseHandler = new VerboseHandler(scheduler.async(), getVersion());
|
||||
@ -206,7 +208,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
configuration.init();
|
||||
|
||||
Set<StorageType> storageTypes = StorageFactory.getRequiredTypes(this, StorageType.H2);
|
||||
DependencyManager.loadStorageDependencies(this, storageTypes);
|
||||
dependencyManager.loadStorageDependencies(storageTypes);
|
||||
|
||||
// register events
|
||||
game.getEventManager().registerListeners(this, new SpongeConnectionListener(this));
|
||||
|
Loading…
Reference in New Issue
Block a user