From e1d59acfb21c99b8b1b0ca0504b599f9ac444d19 Mon Sep 17 00:00:00 2001
From: César Calvo <ccalvo@curisit.net>
Date: Wed, 28 Sep 2016 13:12:11 +0000
Subject: [PATCH] #3347 - Perform MAC Address checking natively

---
 src/main/java/net/curisit/securis/LicenseValidator.java |    2 
 src/main/java/net/curisit/securis/utils/HWInfo.java     |  148 +++++++++++++++++++++++++++++++++++++------------
 src/main/java/net/curisit/securis/ReqGenerator.java     |   12 +++
 pom.xml                                                 |    2 
 4 files changed, 125 insertions(+), 39 deletions(-)

diff --git a/pom.xml b/pom.xml
index 1b3c3a9..01e8fac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>net.curisit</groupId>
 	<artifactId>securis-client</artifactId>
-	<version>1.2.0</version>
+	<version>1.2.1</version>
 	<build>
 		<plugins>
 			<plugin>
diff --git a/src/main/java/net/curisit/securis/LicenseValidator.java b/src/main/java/net/curisit/securis/LicenseValidator.java
index 130a20c..0adcd42 100644
--- a/src/main/java/net/curisit/securis/LicenseValidator.java
+++ b/src/main/java/net/curisit/securis/LicenseValidator.java
@@ -68,7 +68,7 @@
 	}
 
 	public void validateHW(RequestBean reqBean, String appCode, String activationCode) throws SeCurisException {
-		RequestBean currentHW = ReqGenerator.getInstance().createRequest(appCode, activationCode);
+		RequestBean currentHW = ReqGenerator.getInstance().createRequest(appCode, activationCode, true);
 		if (!currentHW.match(reqBean)) {
 			throw new SeCurisException("Current System info mismatch the License System info:\n Licensed: \n" + JsonUtils.toPrettyJSON(reqBean, RequestBean.class)
 					+ "\n Expected: \n" + JsonUtils.toPrettyJSON(currentHW));
diff --git a/src/main/java/net/curisit/securis/ReqGenerator.java b/src/main/java/net/curisit/securis/ReqGenerator.java
index d7565c9..8d595b1 100644
--- a/src/main/java/net/curisit/securis/ReqGenerator.java
+++ b/src/main/java/net/curisit/securis/ReqGenerator.java
@@ -45,17 +45,27 @@
     }
 
     public RequestBean createRequest(String appCode, String activationCode) throws SeCurisException {
+        return createRequest(appCode, activationCode, false);
+    }
+       
+    public RequestBean createRequest(String appCode, String activationCode, boolean nativeMac) throws SeCurisException {
         RequestBean req = new RequestBean();
 
         req.setAppCode(appCode);
         req.setActivationCode(activationCode);
         req.setArch(HWInfo.getArch());
         req.setCrcLogo(getCrcLogo());
-        req.setMacAddresses(HWInfo.getMACAddress());
+        if (nativeMac) {
+        	req.setMacAddresses(HWInfo.getMACAddressNativelyFailback());
+        } else {
+        	req.setMacAddresses(HWInfo.getMACAddress());        	
+        }
         req.setOsName(HWInfo.getOsName());
 
         return req;
     }
+    
+   
 
     public RequestBean loadRequest(File requestFile) throws SeCurisException {
         try {
diff --git a/src/main/java/net/curisit/securis/utils/HWInfo.java b/src/main/java/net/curisit/securis/utils/HWInfo.java
index 0b60796..fd9a831 100644
--- a/src/main/java/net/curisit/securis/utils/HWInfo.java
+++ b/src/main/java/net/curisit/securis/utils/HWInfo.java
@@ -1,15 +1,18 @@
 package net.curisit.securis.utils;
 
-import java.net.InetAddress;
+import java.io.InputStream;
 import java.net.NetworkInterface;
 import java.net.SocketException;
-import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import net.curisit.securis.SeCurisException;
 
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
@@ -21,7 +24,7 @@
  */
 public class HWInfo {
 
-	private static final Logger LOG = LogManager.getLogger(HWInfo.class);
+	private static final Logger log = LogManager.getLogger(HWInfo.class);
 
 	public static String getOsName() {
 		return System.getProperty("os.name");
@@ -36,62 +39,135 @@
 	}
 
 	/**
-	 * Get MAC address
+	 * Gets MAC address using Java. Java does not show information about down interfaces
 	 * 
 	 * @return
 	 */
 	public static List<String> getMACAddress() throws SeCurisException {
+		log.info("Retrieving HW info with Java VM");
 		List<byte[]> macs = new ArrayList<byte[]>();
 		try {
-			// Get MAC for ethX interface, where X is the lower number with MAC address != null
 			for (NetworkInterface network : Collections.list(NetworkInterface.getNetworkInterfaces())) {
 				if (!network.isLoopback() && !network.isVirtual() && !network.isPointToPoint() && network.getHardwareAddress() != null) {
 					macs.add(network.getHardwareAddress());
-					LOG.debug("Interface added {}, MAC: {}", network.getName(), network.getHardwareAddress());
+					log.debug("Interface added {}, MAC: {}", network.getName(), network.getHardwareAddress());
 					logInterface(network);
 				}
 			}
 
-			// If not found interface ethX
 			if (macs.isEmpty()) {
-				NetworkInterface network = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
-				if (network.getHardwareAddress() != null)
-					macs.add(network.getHardwareAddress());
-				LOG.debug("Selected interface (Inet Address rule)");
-				logInterface(network);
-			}
-
-			// If not found interface, last attempt, we get any mac
-			if (macs.isEmpty()) {
-				for (NetworkInterface network : Collections.list(NetworkInterface.getNetworkInterfaces())) {
-					if (!network.isLoopback() && !network.isVirtual() && !network.isPointToPoint() && network.getHardwareAddress() != null) {
-						if (network.getHardwareAddress() != null)
-							macs.add(network.getHardwareAddress());
-						LOG.debug("Selected interface (Any with MAC rule)");
-						logInterface(network);
-						break;
-					}
-				}
-			}
-
-			if (macs.isEmpty())
 				throw new SeCurisException("Unable to get MAC address");
+			}
 
 			List<String> macAddresses = new ArrayList<String>();
 			for (byte[] mac : macs) {
 				macAddresses.add(printMacAddress(mac));
 			}
-			LOG.debug("MAC Addresses: {}", macAddresses);
+			log.info("MAC Addresses: {}", macAddresses);
 			return macAddresses;
 
-		} catch (UnknownHostException e) {
-			throw new SeCurisException("Unable to get MAC address", e);
-		} catch (SocketException e) {
-			throw new SeCurisException("Unable to get MAC address", e);
 		} catch (Exception e) {
 			throw new SeCurisException("Unable to get MAC address", e);
+		} 
+	}
+
+	/**
+	 * Gets MAC address natively using ipconfig or ifconfig.
+	 * @return
+	 * @throws CurisException
+	 */
+	public static List<String> getMACAddressNatively() throws SeCurisException {
+		try {
+			log.info("Retrieving HW info natively");
+			String output;
+			if (isWindows()) {
+				output = executeCommand(new String[] {"ipconfig", "/all"});
+			} else {
+				output = executeCommand(new String[] {"ifconfig", "-a"});
+			}
+			//String output = FileUtils.readFileToString(new File("/Users/cesar/Downloads/ipconfig_no_mac.txt"), "UTF-8");
+			log.debug("Command output {}", output);
+			List<String> macs = extractMacs(output);
+			log.debug("Macs found: {}", macs);
+			return macs;
+		} catch (SeCurisException ce) {
+			throw ce;
 		}
 	}
+	
+	/**
+	 * Tries to retrieve MAC address natively, if it fails then it tries to retrieve it using Java
+	 * @return
+	 * @throws CurisException
+	 */
+	public static List<String> getMACAddressNativelyFailback() throws SeCurisException {
+		try {
+			return getMACAddressNatively();
+		} catch (SeCurisException e) {
+			log.info("Error getting HW info natively" .concat(e.getMessage()));			
+			return getMACAddress();
+		}
+	}	
+	
+	/**
+	 * Finds MAC in a string.  Match string like this:
+	 * Unix: 60:03:08:95:ae:d0
+	 * Windows: 0A-00-27-00-00-00
+	 * 
+	 * @param line
+	 * @return
+	 * @throws CurisException
+	 */
+	private static List<String> extractMacs(String line) throws SeCurisException {
+		Pattern pattern = Pattern.compile("(?m)( )([0-9a-fA-F][0-9a-fA-F][:-]){5}([0-9a-fA-F][0-9a-fA-F])($| )");
+
+		
+		List<String> macs = new ArrayList<>();
+		Matcher matcher = pattern.matcher(line);
+		while(matcher.find()){
+			String mac = matcher.group().trim().replaceAll(":", "-").toUpperCase();
+			if (!mac.equals("00-00-00-00-00-00")) {
+				macs.add(mac);
+			}
+		}
+		
+		if (macs.isEmpty()) {
+			throw new SeCurisException("Mac is not found");
+		}
+		
+		return macs;
+	}	
+
+	/**
+	 * Executes the given command and return the standard output.
+	 * @param command
+	 * @return
+	 * @throws Exception
+	 */
+	private static String executeCommand(String[] command) throws SeCurisException {
+		try {
+			Process process = new ProcessBuilder(command).start();
+			InputStream is = process.getInputStream();
+					
+			String output = IOUtils.toString(is, "UTF-8"); 
+
+			if (process == null || process.exitValue() != 0) {
+				throw new SeCurisException(String.format("Error executing command %s", StringUtils.join(command, " ")));
+			}		
+			return output;
+		} catch (Exception e) {
+			throw new SeCurisException(String.format("Error executing command %s", StringUtils.join(command, " ")), e);
+		}
+	}
+	
+	/**
+	 * Returns true is OOSS is windows
+	 * @return
+	 */
+	public static boolean isWindows() {
+		String os = System.getProperty("os.name").toLowerCase();
+		return (os.indexOf("win") >= 0);
+	}	
 
 	/**
 	 * Get microprocessor name
@@ -103,10 +179,10 @@
 	}
 
 	private static void logInterface(NetworkInterface network) {
-		LOG.debug("Interface name: {}", network.getName());
-		LOG.debug("Interface display name: {}", network.getDisplayName());
+		log.debug("Interface name: {}", network.getName());
+		log.debug("Interface display name: {}", network.getDisplayName());
 		try {
-			LOG.debug("Interface mac: {}", printMacAddress(network.getHardwareAddress()));
+			log.debug("Interface mac: {}", printMacAddress(network.getHardwareAddress()));
 		} catch (SocketException e) {
 			// Silent
 		}

--
Gitblit v1.3.2