diff --git a/README.md b/README.md index e68fe4c..2d713a3 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ JDK 1.7 + com.github.core-lib xjar - 4.0.1 + 4.0.2 @@ -188,7 +188,7 @@ xjar java --add-opens java.base/jdk.internal.loader=ALL-UNNAMED -jar /path/to/en com.github.core-lib xjar-maven-plugin - 4.0.1 + 4.0.2 @@ -262,6 +262,8 @@ mvn clean install -Dxjar.password=io.xjar -Dxjar.targetDir=/directory/to/save/ta 更多文档:[xjar-maven-plugin](https://github.com/core-lib/xjar-maven-plugin) ## 版本记录 +* 4.0.2 + 1. 安全性升级 * 4.0.1 1. 兼容JDK-9及以上版本 * 4.0.0 diff --git a/pom.xml b/pom.xml index d2a4c1c..09c6777 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.xjar xjar - 4.0.1 + 4.0.2 xjar diff --git a/src/main/java/io/xjar/XGo.java b/src/main/java/io/xjar/XGo.java index 94c7b6a..c0ae5cd 100644 --- a/src/main/java/io/xjar/XGo.java +++ b/src/main/java/io/xjar/XGo.java @@ -5,7 +5,9 @@ import java.io.*; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -34,31 +36,34 @@ public static void make(File xJar, XKey xKey) throws IOException { variables.put("xKey.ivsize", convert(ivsize)); variables.put("xKey.password", convert(password)); - URL url = XGo.class.getClassLoader().getResource("xjar/xjar.go"); - if (url == null) { - throw new IOException("could not find xjar.go"); - } - String dir = xJar.getParent(); - File src = new File(dir, "xjar.go"); - try ( - InputStream in = url.openStream(); - Reader reader = new InputStreamReader(in); - BufferedReader br = new BufferedReader(reader); - OutputStream out = new FileOutputStream(src); - Writer writer = new OutputStreamWriter(out); - BufferedWriter bw = new BufferedWriter(writer) - ) { - String line; - while ((line = br.readLine()) != null) { - for (Map.Entry variable : variables.entrySet()) { - line = line.replace("#{" + variable.getKey() + "}", variable.getValue()); + List templates = Arrays.asList("xjar.go", "xjar_agentable.go"); + for (String template : templates) { + URL url = XGo.class.getClassLoader().getResource("xjar/" + template); + if (url == null) { + throw new IOException("could not find xjar/" + template + " in classpath"); + } + String dir = xJar.getParent(); + File src = new File(dir, template); + try ( + InputStream in = url.openStream(); + Reader reader = new InputStreamReader(in); + BufferedReader br = new BufferedReader(reader); + OutputStream out = new FileOutputStream(src); + Writer writer = new OutputStreamWriter(out); + BufferedWriter bw = new BufferedWriter(writer) + ) { + String line; + while ((line = br.readLine()) != null) { + for (Map.Entry variable : variables.entrySet()) { + line = line.replace("#{" + variable.getKey() + "}", variable.getValue()); + } + bw.write(line); + bw.write(CLRF); } - bw.write(line); - bw.write(CLRF); + bw.flush(); + writer.flush(); + out.flush(); } - bw.flush(); - writer.flush(); - out.flush(); } } diff --git a/src/main/resources/xjar/xjar.go b/src/main/resources/xjar/xjar.go index e08c6fc..956c69e 100644 --- a/src/main/resources/xjar/xjar.go +++ b/src/main/resources/xjar/xjar.go @@ -10,6 +10,7 @@ import ( "os" "os/exec" "path/filepath" + "strings" ) var xJar = XJar{ @@ -55,6 +56,18 @@ func main() { panic(errors.New("invalid jar with SHA-1")) } + // check agent forbid + { + args := os.Args + l := len(args) + for i := 0; i < l; i++ { + arg := args[i] + if strings.HasPrefix(arg, "-javaagent:") { + panic(errors.New("agent forbidden")) + } + } + } + // start java application java := os.Args[1] args := os.Args[2:] diff --git a/src/main/resources/xjar/xjar_agentable.go b/src/main/resources/xjar/xjar_agentable.go new file mode 100644 index 0000000..e08c6fc --- /dev/null +++ b/src/main/resources/xjar/xjar_agentable.go @@ -0,0 +1,134 @@ +package main + +import ( + "bytes" + "crypto/md5" + "crypto/sha1" + "errors" + "hash" + "io" + "os" + "os/exec" + "path/filepath" +) + +var xJar = XJar{ + md5: []byte{#{xJar.md5}}, + sha1: []byte{#{xJar.sha1}}, +} + +var xKey = XKey{ + algorithm: []byte{#{xKey.algorithm}}, + keysize: []byte{#{xKey.keysize}}, + ivsize: []byte{#{xKey.ivsize}}, + password: []byte{#{xKey.password}}, +} + +func main() { + // search the jar to start + jar, err := JAR(os.Args) + if err != nil { + panic(err) + } + + // parse jar name to absolute path + path, err := filepath.Abs(jar) + if err != nil { + panic(err) + } + + // verify jar with MD5 + MD5, err := MD5(path) + if err != nil { + panic(err) + } + if bytes.Compare(MD5, xJar.md5) != 0 { + panic(errors.New("invalid jar with MD5")) + } + + // verify jar with SHA-1 + SHA1, err := SHA1(path) + if err != nil { + panic(err) + } + if bytes.Compare(SHA1, xJar.sha1) != 0 { + panic(errors.New("invalid jar with SHA-1")) + } + + // start java application + java := os.Args[1] + args := os.Args[2:] + key := bytes.Join([][]byte{ + xKey.algorithm, {13, 10}, + xKey.keysize, {13, 10}, + xKey.ivsize, {13, 10}, + xKey.password, {13, 10}, + }, []byte{}) + cmd := exec.Command(java, args...) + cmd.Stdin = bytes.NewReader(key) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + if err != nil { + panic(err) + } +} + +// find jar name from args +func JAR(args []string) (string, error) { + var jar string + + l := len(args) + for i := 1; i < l-1; i++ { + arg := args[i] + if arg == "-jar" { + jar = args[i+1] + } + } + + if jar == "" { + return "", errors.New("unspecified jar name") + } + + return jar, nil +} + +// calculate file's MD5 +func MD5(path string) ([]byte, error) { + return HASH(path, md5.New()) +} + +// calculate file's SHA-1 +func SHA1(path string) ([]byte, error) { + return HASH(path, sha1.New()) +} + +// calculate file's HASH value with specified HASH Algorithm +func HASH(path string, hash hash.Hash) ([]byte, error) { + file, err := os.Open(path) + + if err != nil { + return nil, err + } + + _, _err := io.Copy(hash, file) + if _err != nil { + return nil, _err + } + + sum := hash.Sum(nil) + + return sum, nil +} + +type XJar struct { + md5 []byte + sha1 []byte +} + +type XKey struct { + algorithm []byte + keysize []byte + ivsize []byte + password []byte +}