From 846bd47fcfaad67d97a4d0237e4d6424cbdbf396 Mon Sep 17 00:00:00 2001 From: tkellner Date: Tue, 7 Jan 2014 14:43:45 +0000 Subject: Manually search libpcsclite path under linux git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@1273 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/util/LinuxLibraryFinder.java | 192 +++++++++++++++++++++ .../main/java/at/gv/egiz/smcc/util/SMCCHelper.java | 14 ++ 2 files changed, 206 insertions(+) create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/util/LinuxLibraryFinder.java (limited to 'smcc/src/main') diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/LinuxLibraryFinder.java b/smcc/src/main/java/at/gv/egiz/smcc/util/LinuxLibraryFinder.java new file mode 100644 index 00000000..5aed2c2d --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/util/LinuxLibraryFinder.java @@ -0,0 +1,192 @@ +/**************************************************************************** + * Copyright (C) 2013 ecsec GmbH. + * All rights reserved. + * Contact: ecsec GmbH (info@ecsec.de) + * + * This file is part of the Open eCard App. + * + * GNU General Public License Usage + * This file may be used under the terms of the GNU General Public + * License version 3.0 as published by the Free Software Foundation + * and appearing in the file LICENSE.GPL included in the packaging of + * this file. Please review the following information to ensure the + * GNU General Public License version 3.0 requirements will be met: + * http://www.gnu.org/copyleft/gpl.html. + * + * Other Usage + * Alternatively, this file may be used in accordance with the terms + * and conditions contained in a signed written agreement between + * you and ecsec GmbH. + * + ***************************************************************************/ + +package at.gv.egiz.smcc.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Helper class to find shared object (.so) libraries in linux systems. The + * algorithm to find the objects is the same as used in the dynamic loader ld. + * There is one exception to this rule, the ELF variables DT_RPATH and + * DT_RUNPATH are not evaluated, because they are not available in java. + * + * @author Tobias Wich + */ +public class LinuxLibraryFinder { + + private static final Logger logger = LoggerFactory + .getLogger(LinuxLibraryFinder.class); + + /** + * Gets a file object pointing to the library which has been searched. On + * success, the file points to first file found which is readable and thus can + * be used. + *

+ * The algorithm to find the library can be found in the ld.so(8) manpage and + * is as follows: + *

    + *
  1. Check paths in {@code LD_LIBRARY_PATH} environment variable.
  2. + *
  3. Check for library in {@code /etc/ld.so.cache} by executing + * {@code ldconfig -p} and searching the output.
  4. + *
  5. Check the base library paths {@code /lib} and {@code /usr/lib} or + * {@code /lib64} and {@code /usr/lib64} depending on the architecture.
  6. + *
+ *

+ * + * @param name + * Name of the library, such as pcsclite. + * @param version + * Version suffix such as 1, 1.0 or null if no suffix is desired. + * @return The file object to the library. + */ + public static File getLibraryPath(String name, String version) + throws FileNotFoundException { + // add version only if it has a meaningful value + version = version == null ? "" : version; + version = version.isEmpty() ? "" : ("." + version); + String libname = System.mapLibraryName(name) + version; + + File result; + // LD_LIBRARY_PATH + result = findInEnv(libname, System.getenv("LD_LIBRARY_PATH")); + if (result != null) { + return result; + } + // ld.so.cache + result = findInLdCache(libname); + if (result != null) { + return result; + } + // base lib paths + result = findInBaseLibPaths(libname); + if (result != null) { + return result; + } + + throw new FileNotFoundException("Library " + libname + + " not found on your system."); + } + + private static File findInEnv(String libname, String env) { + if (env != null) { + for (String path : env.split(":")) { + // append lib to path and see if it exists + String result = path + "/" + libname; + File test = new File(result.trim()); + if (test.canRead()) { + return test; + } + } + } + // nothing found + return null; + } + + private static File findInLdCache(String libname) { + String ldconfExec = findProgramFile("ldconfig") + " -p"; + Process p = null; + try { + p = Runtime.getRuntime().exec(ldconfExec); + InputStream cacheData = p.getInputStream(); + BufferedReader cacheDataReader = new BufferedReader( + new InputStreamReader(cacheData)); + String next; + while ((next = cacheDataReader.readLine()) != null) { + if (next.endsWith(libname)) { + // extract library path from entry + // the line can look like this: + // libpcsclite.so.1 (libc6,x86-64) => + // /usr/lib/x86_64-linux-gnu/libpcsclite.so.1 + int endIdx = next.lastIndexOf("=>"); + if (endIdx != -1) { + String result = next.substring(endIdx + 2); + File test = new File(result.trim()); + if (test.canRead()) { + return test; + } + } + } + } + } catch (IOException ex) { + logger.debug("Library {} not found in ld.so.cache.", libname); + } finally { + if (p != null) { + try { + p.getInputStream().close(); + } catch (IOException ex) { + // dafuq?!? + } + try { + p.getOutputStream().close(); + } catch (IOException ex) { + // dafuq?!? + } + try { + p.getErrorStream().close(); + } catch (IOException ex) { + // dafuq?!? + } + } + } + return null; + } + + private static String findProgramFile(String name) { + String path = System.getenv().get("PATH"); + path = path == null ? "" : path; + path = "/sbin:/usr/sbin:" + path; + // loop through entries and find program + for (String entry : path.split(":")) { + String fname = entry + "/" + name; + File f = new File(fname); + if (f.canExecute()) { + return fname; + } + } + // nothing found, maybe the file is in the same path + return name; + } + + private static File findInBaseLibPaths(String libname) { + String archSuffix = "64".equals(System.getProperty("sun.arch.data.model")) ? "64" + : ""; + String[] basePaths = { "/lib" + archSuffix, "/usr/lib" + archSuffix }; + // look for lib in those paths + for (String path : basePaths) { + String fname = path + "/" + libname; + File test = new File(fname); + if (test.canRead()) { + return test; + } + } + return null; + } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java index 54c831cc..61bde48c 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java @@ -24,6 +24,8 @@ package at.gv.egiz.smcc.util; +import java.io.File; +import java.io.FileNotFoundException; import java.math.BigInteger; import java.util.Locale; import java.util.Map; @@ -77,6 +79,18 @@ public class SMCCHelper { } return; } + + String osName = System.getProperty("os.name"); + if (osName.startsWith("Linux")) { + File libFile; + try { + libFile = LinuxLibraryFinder.getLibraryPath("pcsclite", "1"); + System.setProperty("sun.security.smartcardio.library", libFile.getAbsolutePath()); + } catch (FileNotFoundException e) { + log.error("PC/SC library not found", e); + } + } + signatureCard = null; resultCode = NO_CARD; // find pcsc support -- cgit v1.2.3