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/utils/HWInfo.java |  148 +++++++++++++++++++++++++++++++++++++------------
 1 files changed, 112 insertions(+), 36 deletions(-)

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