/** * *************************************************************************** * Copyright (c) 2017, TigerGraph Inc. * All rights reserved * Unauthorized copying of this file, via any medium is * strictly prohibited * Proprietary and confidential * **************************************************************************** */ package com.tigergraph.v2_4_1.client; import com.tigergraph.v2_4_1.common.Constant; import com.tigergraph.v2_4_1.common.GSQL_LOG; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.util.Properties; import jline.console.ConsoleReader; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; /** * This class define several static utility methods. * * <p>This class is a final class and cannot be extended. */ public final class Util { public static String LOG_DIR; public static String SESSION; /** Grep IUM config from gsql.cfg file. */ public static String getIUMConfig(String config) { String cmd = "grep " + config + " ~/.gsql/gsql.cfg | cut -d ' ' -f 2"; return getStringFromBashCmd(cmd); } /** * load the CA and use it in the https connection * @param filename the CA filename * @return the SSL context */ public static SSLContext getSSLContext(String filename) throws Exception { try { // Load CAs from an InputStream // (could be from a resource or ByteArrayInputStream or ...) // X.509 is a standard that defines the format of public key certificates, used in TLS/SSL. CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = new BufferedInputStream(new FileInputStream(filename)); Certificate ca = cf.generateCertificate(caInput); // Create a KeyStore containing our trusted CAs String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); // Create a TrustManager that trusts the CAs in our KeyStore String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); // Create an SSLContext that uses our TrustManager SSLContext context = SSLContext.getInstance("TLS"); context.init(null, tmf.getTrustManagers(), null); return context; } catch (Exception e) { throw new Exception("Failed to load the CA file: " + e.getMessage(), e); } } public static void LogText(String text) { if (GSQL_LOG.LOG_FILE == null) return; try { GSQL_LOG.LogInfo(text, SESSION, 1); } catch (Exception e) { } } public static void LogExceptions(Throwable e) { if (GSQL_LOG.LOG_FILE == null) return; try { GSQL_LOG.LogExceptions(e, SESSION, 1); } catch (Exception ioe) { } } public static void setClientLogFile(String username, String serverip, boolean printerror) { try { GSQL_LOG.LOG_FILE = Util.getClientLogFile("log", username, serverip, true).getPath(); PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(GSQL_LOG.LOG_FILE, true))); writer.print(""); } catch (Exception e) { GSQL_LOG.LOG_FILE = null; if (printerror) System.out.println("Can't open log file, " + e.getMessage()); } Util.LogText("Client commit: " + Util.getCommitClient()); } public static File getClientLogFile(String file, String username, String serverip, boolean rotate) throws IOException { if (Util.LOG_DIR == null) { throw new IOException("LogDir is null"); } String filename = Util.LOG_DIR + "/" + file + "."; filename += Math.abs((username + "." + serverip).hashCode()) % 1000000; File f = new File(filename); if (!f.getParentFile().isDirectory()) { f.getParentFile().mkdirs(); } if (!f.exists()) { //create file if it does not exist f.createNewFile(); } else if (rotate && f.length() > Constant.LogRotateSize) { // rotate log file when file is large than 500M long current = System.currentTimeMillis(); // copy the log to a new file with timestamp String LogCopy = filename + "." + current / 1000; Files.move(f.toPath(), Paths.get(LogCopy), StandardCopyOption.REPLACE_EXISTING); } return f; } /** * Create a prompt with color and customized prompt text. * @param text, the prompt text * @return input string */ public static String ColorPrompt(String text) { String ANSI_BLUE = "\u001B[1;34m"; String ANSI_RESET = "\u001B[0m"; String input = null; try { ConsoleReader tempConsole = new ConsoleReader(); String prmpt = ANSI_BLUE + text + ANSI_RESET; tempConsole.setPrompt(prmpt); input = tempConsole.readLine(); } catch (IOException e) { LogExceptions(e); System.out.println("Prompt input error!"); } return input; } /** * function to prompt to generate a prompt for user to input username * @return input user name */ public static String Prompt4UserName() { return ColorPrompt("User Name : "); } /** * function to generate a prompt for user to input username * @param doubleCheck, notes whether the password should be confirmed one more time. * @param isNew, indicates whether it is inputting a new password * @return SHA-1 hashed password on success, null on error */ public static String Prompt4Password(boolean doubleCheck, boolean isNew, String username) { String ANSI_BLUE = "\u001B[1;34m"; String ANSI_RESET = "\u001B[0m"; String pass = null; try { ConsoleReader tempConsole = new ConsoleReader(); String prompttext = isNew ? "New Password : " : "Password for " + username + " : "; String prompt = ANSI_BLUE + prompttext + ANSI_RESET; tempConsole.setPrompt(prompt); tempConsole.setExpandEvents(false); String pass1 = tempConsole.readLine(new Character('*')); if (doubleCheck) { String pass2 = pass1; prompt = ANSI_BLUE + "Re-enter Password : " + ANSI_RESET; tempConsole.setPrompt(prompt); pass2 = tempConsole.readLine(new Character('*')); if (!pass1.equals(pass2)) { System.out.println("The two passwords do not match."); return null; } } // need to hash the password so that we do not store it as plain text pass = pass1; } catch (Exception e) { LogExceptions(e); System.out.println("Error while inputting password."); } return pass; } public static int getTerminalWidth() { int width = 80; // for windows system, just use a default value if (isWindows()) { return width; } // NOTE: The "tput" commands computes terminal length only when the stderr is redirected to // current tty ---- /dev/tty. This will not work for Windows. String result = Util.getStringFromBashCmd("tput cols 2> /dev/tty"); if (result != null && !result.isEmpty()) { try { width = Integer.parseInt(result); } catch (NumberFormatException e) { width = 80; } } return width; } public static boolean isWindows() { String OS = System.getProperty("os.name").toLowerCase(); return (OS.indexOf("win") >= 0); } public static String getStringFromBashCmd(String cmd) { try { ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd); Process p = pb.start(); BufferedReader output = new BufferedReader(new InputStreamReader(p.getInputStream())); p.waitFor(); //get output (only one line) String result = output.readLine(); return result; } catch (Exception e) { LogExceptions(e); return null; } } public static String getCommitClient() { if (true) return "47229e675f792374d4525afe6ea10898decc2e44"; String clientCommitHash = null; try { Properties props = new Properties(); InputStream in = Util.class.getClassLoader().getResourceAsStream("Version.prop"); props.load(in); in.close(); clientCommitHash = props.getProperty("commit_client"); } catch (Exception e) { LogExceptions(e); System.out.println("Can't find Version.prop."); } return clientCommitHash; } }