mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-28 21:56:33 +01:00
Verify integrity of downloaded jars
The bukkit plugins download jar files from Curse and then load those as plugins, i.e. they're running downloaded code. In order to increase security, this commit adds logic to verify the SHA-256 hash of the downloaded jar files.
This commit is contained in:
parent
531ff8f4a2
commit
e20f03d72e
@ -1,12 +1,10 @@
|
|||||||
package com.boydti.fawe.bukkit;
|
package com.boydti.fawe.bukkit;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.util.Jars;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.channels.Channels;
|
|
||||||
import java.nio.channels.ReadableByteChannel;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -57,11 +55,9 @@ public class BukkitMain extends JavaPlugin {
|
|||||||
if (Bukkit.getPluginManager().getPlugin("WorldEdit") == null) {
|
if (Bukkit.getPluginManager().getPlugin("WorldEdit") == null) {
|
||||||
try {
|
try {
|
||||||
File output = new File(this.getDataFolder().getParentFile(), "WorldEdit.jar");
|
File output = new File(this.getDataFolder().getParentFile(), "WorldEdit.jar");
|
||||||
URL worldEditUrl = new URL("https://addons.cursecdn.com/files/2431/372/worldedit-bukkit-6.1.7.2.jar");
|
byte[] weJar = Jars.WE_B_6_1_7_2.download();
|
||||||
try (ReadableByteChannel rbc = Channels.newChannel(worldEditUrl.openStream())) {
|
|
||||||
try (FileOutputStream fos = new FileOutputStream(output)) {
|
try (FileOutputStream fos = new FileOutputStream(output)) {
|
||||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
fos.write(weJar);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Bukkit.getPluginManager().loadPlugin(output);
|
Bukkit.getPluginManager().loadPlugin(output);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
67
core/src/main/java/com/boydti/fawe/util/Jars.java
Normal file
67
core/src/main/java/com/boydti/fawe/util/Jars.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package com.boydti.fawe.util;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.google.common.io.BaseEncoding;
|
||||||
|
|
||||||
|
public enum Jars {
|
||||||
|
WE_B_6_1_7_2("https://addons.cursecdn.com/files/2431/372/worldedit-bukkit-6.1.7.2.jar",
|
||||||
|
"711be37301a327aba4e347131875d0564dbfdc2f41053a12db97f0234661778b", 1726340),
|
||||||
|
|
||||||
|
VS_B_5_171_0("https://addons-origin.cursecdn.com/files/912/511/VoxelSniper-5.171.0-SNAPSHOT.jar",
|
||||||
|
"292c3b38238e0d8e5f036381d28bccfeb15df67cae53d28b52d066bc6238208f", 3632776);
|
||||||
|
|
||||||
|
public final String url;
|
||||||
|
public final int filesize;
|
||||||
|
public final String digest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param url
|
||||||
|
* Where this jar can be found and downloaded
|
||||||
|
* @param digest
|
||||||
|
* The SHA-256 hexadecimal digest
|
||||||
|
* @param filesize
|
||||||
|
* Size of this jar in bytes
|
||||||
|
*/
|
||||||
|
private Jars(String url, String digest, int filesize) {
|
||||||
|
this.url = url;
|
||||||
|
this.digest = digest;
|
||||||
|
this.filesize = filesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** download a jar, verify hash, return byte[] containing the jar */
|
||||||
|
public byte[] download() throws IOException {
|
||||||
|
byte[] jarBytes = new byte[this.filesize];
|
||||||
|
URL url = new URL(this.url);
|
||||||
|
try (DataInputStream dis = new DataInputStream(url.openConnection().getInputStream());) {
|
||||||
|
dis.readFully(jarBytes);
|
||||||
|
if (dis.read() != -1) { // assert that we've read everything
|
||||||
|
throw new IllegalStateException("downloaded jar is longer than expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageDigest md;
|
||||||
|
md = MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] thisDigest = md.digest(jarBytes);
|
||||||
|
byte[] realDigest = BaseEncoding.base16().decode(this.digest.toUpperCase());
|
||||||
|
|
||||||
|
if (Arrays.equals(thisDigest, realDigest)) {
|
||||||
|
Fawe.debug("++++ HASH CHECK ++++");
|
||||||
|
Fawe.debug(this.url);
|
||||||
|
Fawe.debug(BaseEncoding.base16().encode(thisDigest));
|
||||||
|
return jarBytes;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("downloaded jar does not match the hash");
|
||||||
|
}
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
// Shouldn't ever happen, Minecraft won't even run on such a JRE
|
||||||
|
throw new IllegalStateException("Your JRE does not support SHA-256");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
|
|||||||
import com.boydti.fawe.bukkit.BukkitCommand;
|
import com.boydti.fawe.bukkit.BukkitCommand;
|
||||||
import com.boydti.fawe.object.FaweCommand;
|
import com.boydti.fawe.object.FaweCommand;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
|
import com.boydti.fawe.util.Jars;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.thevoxelbox.voxelsniper.RangeBlockHelper;
|
import com.thevoxelbox.voxelsniper.RangeBlockHelper;
|
||||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||||
@ -12,9 +13,6 @@ import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
|||||||
import com.thevoxelbox.voxelsniper.command.VoxelVoxelCommand;
|
import com.thevoxelbox.voxelsniper.command.VoxelVoxelCommand;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.channels.Channels;
|
|
||||||
import java.nio.channels.ReadableByteChannel;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -40,11 +38,9 @@ public class Favs extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
if (output == null) {
|
if (output == null) {
|
||||||
output = new File(this.getDataFolder().getParentFile(), "VoxelSniper.jar");
|
output = new File(this.getDataFolder().getParentFile(), "VoxelSniper.jar");
|
||||||
URL worldEditUrl = new URL("https://addons-origin.cursecdn.com/files/912/511/VoxelSniper-5.171.0-SNAPSHOT.jar");
|
byte[] vsJar = Jars.VS_B_5_171_0.download();
|
||||||
try (ReadableByteChannel rbc = Channels.newChannel(worldEditUrl.openStream())) {
|
|
||||||
try (FileOutputStream fos = new FileOutputStream(output)) {
|
try (FileOutputStream fos = new FileOutputStream(output)) {
|
||||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
fos.write(vsJar);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Bukkit.getPluginManager().loadPlugin(output);
|
Bukkit.getPluginManager().loadPlugin(output);
|
||||||
|
Loading…
Reference in New Issue
Block a user