Commit ab7ef744 authored by Tobias Wich's avatar Tobias Wich
Browse files

Merge branch 'master' into reqesidta

parents 3ca2efe7 8ed7db8f
/****************************************************************************
* Copyright (C) 2012-2018 ecsec GmbH.
* Copyright (C) 2012-2019 ecsec GmbH.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
......@@ -24,13 +24,9 @@ package org.openecard.scio;
import java.io.File;
import java.io.FileNotFoundException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.NoSuchAlgorithmException;
import javax.smartcardio.CardTerminals;
import javax.smartcardio.TerminalFactory;
import org.openecard.common.ifd.scio.SCIOErrorCode;
import jnasmartcardio.Smartcardio;
import org.openecard.common.ifd.scio.SCIOTerminals;
import org.openecard.common.util.LinuxLibraryFinder;
import org.slf4j.Logger;
......@@ -63,12 +59,24 @@ public class PCSCFactory implements org.openecard.common.ifd.scio.TerminalFactor
File libFile = LinuxLibraryFinder.getLibraryPath("pcsclite", "1");
System.setProperty("sun.security.smartcardio.library", libFile.getAbsolutePath());
}
loadPCSC();
try {
LOG.info("Trying to initialize PCSC subsystem.");
terminalFactory = TerminalFactory.getInstance(ALGORITHM, null, new Smartcardio());
LOG.info("Successfully initialized PCSC subsystem.");
} catch (NoSuchAlgorithmException ex) {
LOG.error("Failed to initialize smartcard system.");
throw ex;
}
}
@Override
public String getType() {
return terminalFactory.getType();
if (terminalFactory != null) {
return terminalFactory.getType();
} else {
return "PC/SC";
}
}
@Override
......@@ -80,80 +88,4 @@ public class PCSCFactory implements org.openecard.common.ifd.scio.TerminalFactor
return terminalFactory;
}
private static Integer versionCompare(String str1, String str2) {
// code taken from http://stackoverflow.com/a/6702029
String[] vals1 = str1.split("\\.");
String[] vals2 = str2.split("\\.");
int i = 0;
while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) {
i++;
}
if (i < vals1.length && i < vals2.length) {
return Integer.signum(Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i])));
}
return Integer.signum(vals1.length - vals2.length);
}
final void loadPCSC() throws NoSuchAlgorithmException {
terminalFactory = TerminalFactory.getInstance(ALGORITHM, null);
}
void reloadPCSC() {
try {
// code taken from http://stackoverflow.com/questions/16921785/
Class pcscterminal = Class.forName("sun.security.smartcardio.PCSCTerminals");
Field contextId = pcscterminal.getDeclaredField("contextId");
contextId.setAccessible(true);
if (contextId.getLong(pcscterminal) != 0L) {
// First get a new context value
Class pcsc = Class.forName("sun.security.smartcardio.PCSC");
Method SCardEstablishContext = pcsc.getDeclaredMethod("SCardEstablishContext", Integer.TYPE);
SCardEstablishContext.setAccessible(true);
Field SCARD_SCOPE_USER = pcsc.getDeclaredField("SCARD_SCOPE_USER");
SCARD_SCOPE_USER.setAccessible(true);
long newId = ((Long) SCardEstablishContext.invoke(pcsc, SCARD_SCOPE_USER.getInt(pcsc)));
contextId.setLong(pcscterminal, newId);
// Then clear the terminals in cache
loadPCSC();
CardTerminals terminals = terminalFactory.terminals();
Field fieldTerminals = pcscterminal.getDeclaredField("terminals");
fieldTerminals.setAccessible(true);
Class classMap = Class.forName("java.util.Map");
Method clearMap = classMap.getDeclaredMethod("clear");
clearMap.invoke(fieldTerminals.get(terminals));
}
} catch (NoSuchAlgorithmException ex) {
// if it worked once it will work again
String msg = "PCSC changed it's algorithm. There is something really wrong.";
LOG.error(msg, ex);
throw new RuntimeException("PCSC changed it's algorithm. There is something really wrong.");
} catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException | NoSuchMethodException |
SecurityException ex) {
LOG.error("Failed to perform reflection magic to reload TerminalFactory.", ex);
} catch (InvocationTargetException ex) {
if (PCSCExceptionExtractor.hasPCSCException(ex)) {
SCIOErrorCode code = PCSCExceptionExtractor.getCode(ex);
if (code == SCIOErrorCode.SCARD_E_NO_SERVICE) {
// silent drop after giving the system some time to recover for themselves
try {
Thread.sleep(5000);
} catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
}
return;
}
}
LOG.error("Error while invoking PCSC restart functionality.");
}
}
}
/****************************************************************************
* Copyright (C) 2014-2015 TU Darmstadt.
* Copyright (C) 2014-2019 TU Darmstadt.
* All rights reserved.
* Contact: ecsec GmbH (info@ecsec.de)
*
......@@ -33,6 +33,7 @@ import javax.annotation.Nonnull;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CardTerminals;
import jnasmartcardio.Smartcardio;
import org.openecard.common.ifd.scio.NoSuchTerminal;
import org.openecard.common.ifd.scio.SCIOErrorCode;
import org.openecard.common.ifd.scio.SCIOException;
......@@ -62,16 +63,36 @@ public class PCSCTerminals implements SCIOTerminals {
PCSCTerminals(@Nonnull PCSCFactory terminalFactory) {
this.terminalFactory = terminalFactory;
loadTerminals();
}
private void reloadFactory() {
terminalFactory.reloadPCSC();
loadTerminals();
terminals = new CardTerminals() {
@Override
public List<CardTerminal> list(CardTerminals.State arg0) throws CardException {
if (loadTerminals()) {
return terminals.list(arg0);
} else {
throw new Smartcardio.JnaPCSCException(SCIOErrorCode.getLong(SCIOErrorCode.SCARD_E_NO_SERVICE), "Error loading PCSC subsystem.");
}
}
@Override
public boolean waitForChange(long arg0) throws CardException {
if (loadTerminals()) {
return terminals.waitForChange(arg0);
} else {
throw new Smartcardio.JnaPCSCException(SCIOErrorCode.getLong(SCIOErrorCode.SCARD_E_NO_SERVICE), "Error loading PCSC subsystem.");
}
}
};
}
private void loadTerminals() {
terminals = terminalFactory.getRawFactory().terminals();
private boolean loadTerminals() {
try {
terminals = terminalFactory.getRawFactory().terminals();
return true;
} catch (Smartcardio.EstablishContextException ex) {
LOG.debug("Failed to load PCSC terminals.", ex);
return false;
}
}
@Override
......@@ -101,7 +122,7 @@ public class PCSCTerminals implements SCIOTerminals {
} else if (code == SCIOErrorCode.SCARD_E_NO_SERVICE || code == SCIOErrorCode.SCARD_E_SERVICE_STOPPED) {
if (firstTry) {
LOG.debug("No service available exception, reloading PCSC and trying again.");
reloadFactory();
loadTerminals();
return list(state, false);
} else {
LOG.debug("No service available exception, returning empty list.");
......@@ -222,11 +243,9 @@ public class PCSCTerminals implements SCIOTerminals {
return Collections.emptyList();
} else if (code == SCIOErrorCode.SCARD_E_NO_SERVICE || code == SCIOErrorCode.SCARD_E_SERVICE_STOPPED || code == SCIOErrorCode.SCARD_E_INVALID_HANDLE) {
LOG.debug("No service available exception, reloading PCSC and returning empty list.");
parent.reloadFactory();
parent.loadTerminals();
own.loadTerminals();
return Collections.emptyList();
} else if (code == SCIOErrorCode.SCARD_E_INVALID_HANDLE) {
// don't log in order to prevent flooding
} else {
LOG.error(msg, ex);
}
......@@ -405,7 +424,7 @@ public class PCSCTerminals implements SCIOTerminals {
case SCARD_E_NO_SERVICE:
case SCARD_E_SERVICE_STOPPED:
LOG.debug("No service available exception, reloading PCSC.");
parent.reloadFactory();
parent.loadTerminals();
own.loadTerminals();
case SCARD_E_NO_READERS_AVAILABLE:
// send events that everything is removed if there are any terminals connected right now
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>org.openecard</groupId>
<artifactId>ifd</artifactId>
<version>1.3.1-SNAPSHOT</version>
<version>1.4.0-rc.4-SNAPSHOT</version>
</parent>
<groupId>org.openecard.ifd</groupId>
......
......@@ -4,8 +4,9 @@
<parent>
<groupId>org.openecard</groupId>
<artifactId>app</artifactId>
<version>1.3.1-SNAPSHOT</version>
<artifactId>src-parent</artifactId>
<version>1.4.0-rc.4-SNAPSHOT</version>
<relativePath>../src-parent/</relativePath>
</parent>
<groupId>org.openecard</groupId>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openecard</groupId>
<artifactId>app</artifactId>
<version>1.4.0-rc.4-SNAPSHOT</version>
</parent>
<groupId>org.openecard</groupId>
<artifactId>packager</artifactId>
<packaging>pom</packaging>
<name>Packager</name>
<modules>
<module>richclient-bundle</module>
<module>richclient-packager</module>
</modules>
</project>
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>fat-jar</id>
<!-- This JAR bundles all dependencies which are not modularized -->
<id>bundle</id>
<formats>
<format>jar</format>
</formats>
......@@ -12,6 +13,7 @@
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
<!-- Modularized dependencies will be excluded, they will become part of the runtime later -->
<excludes>
<!-- BouncyCastle dependencies -->
<exclude>org.bouncycastle:*</exclude>
......
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openecard</groupId>
<artifactId>packager</artifactId>
<version>1.4.0-rc.4-SNAPSHOT</version>
</parent>
<groupId>org.openecard.clients</groupId>
<artifactId>richclient-bundle</artifactId>
<packaging>jar</packaging>
<name>Rich Client (Bundle)</name>
<properties>
<maven.compiler.release>11</maven.compiler.release>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>org.openecard.richclient.RichClient</mainClass>
</manifest>
</archive>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.openecard.clients</groupId>
<artifactId>richclient</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
......@@ -25,17 +25,22 @@ module org.openecard.richclient {
requires java.smartcardio;
requires java.logging;
requires java.desktop;
requires java.sql; // for jackson serialization
/* BouncyCastle modules */
requires org.bouncycastle.provider;
requires org.bouncycastle.tls;
requires org.bouncycastle.pkix;
/* JAXB module */
requires java.xml.bind;
/* JavaFX modules */
requires javafx.base;
requires javafx.controls;
requires javafx.graphics;
/* Open JAXB classes for reflection */
opens de.bund.bsi.ecard.api._1;
opens iso.std.iso_iec._24727.tech.schema;
opens oasis.names.tc.dss._1_0.core.schema;
......@@ -56,4 +61,6 @@ module org.openecard.richclient {
opens org.openecard.mdlw.sal.config to java.xml.bind;
opens org.openecard.addon.manifest to java.xml.bind;
opens jnasmartcardio to java.base;
}
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openecard</groupId>
<artifactId>packager</artifactId>
<version>1.4.0-rc.4-SNAPSHOT</version>
</parent>
<groupId>org.openecard.clients</groupId>
<artifactId>richclient-packager</artifactId>
<packaging>pom</packaging>
<name>Rich Client (Packager)</name>
<properties>
<maven.compiler.release>11</maven.compiler.release>
<app.identifier>Open-eCard-App</app.identifier>
<app.name>Open eCard App</app.name>
<app.vendor>ecsec GmbH</app.vendor>
<app.maintainer>tobias.wich@ecsec.de</app.maintainer>
<app.url>https://openecard.org</app.url>
<app.description>Client side implementation of the eCard-API-Framework (BSI TR-03112)</app.description>
<package.identifier>open-ecard-app</package.identifier>
<package.deps>pcscd</package.deps>
</properties>
<profiles>
<profile>
<id>desktop-package</id>
<activation>
<property>
<name>desktop-package</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>net.agilhard.maven.plugins</groupId>
<artifactId>jlink-jpackager-maven-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>jpackage</id>
<phase>package</phase>
<goals>
<goal>jpackager</goal>
</goals>
<configuration>
<!-- Jpackage arguments -->
<!-- Don't use spaces in application name, because of problems with install scripts ... -->
<identifier>org.openecard.richclient</identifier>
<appVersion>${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}</appVersion>
<module>org.openecard.richclient/org.openecard.richclient.RichClient</module>
<jdkToolchain>
<version>[14,)</version>
</jdkToolchain>
<runtimeImage>${project.build.directory}/open-ecard</runtimeImage>
<skipModulesInclude>true</skipModulesInclude>
<!-- JVM arguments of the application -->
<jvmArgs>
<jvmArg>-XX:-UsePerfData</jvmArg>
<jvmArg>-XX:-Inline</jvmArg>
<jvmArg>-XX:+AggressiveOpts</jvmArg>
<jvmArg>-Xms16m</jvmArg>
<jvmArg>-Xmx64m</jvmArg>
<jvmArg>-XX:+UseG1GC</jvmArg>
<jvmArg>-XX:MinHeapFreeRatio=1</jvmArg>
<jvmArg>-XX:MaxHeapFreeRatio=5</jvmArg>
<jvmArg>-XX:G1ReservePercent=5</jvmArg>
<jvmArg>-Djavax.xml.stream.isSupportingExternalEntities=false</jvmArg>
<jvmArg>-Djavax.xml.stream.supportDTD=false</jvmArg>
</jvmArgs>
<!-- Application package metadata -->
<vendor>${app.vendor}</vendor>
<description>${app.description}</description>
<licenseFile>${project.basedir}/src/main/resources/licenses/LICENSE.GPL</licenseFile>
<copyright>2019 ecsec GmbH</copyright>
<linuxOptions>
<bundleName>${package.identifier}</bundleName>
<debMaintainer>${app.maintainer}</debMaintainer>
<rpmLicenseType>GPL v3</rpmLicenseType>
<menuGroup>Network;</menuGroup>
<packageDeps>${package.deps}</packageDeps>
</linuxOptions>
<macOptions>
<bundleName>${app.identifier}</bundleName>
<bundleIdentifier>org.openecard.versioncheck.MainLoader</bundleIdentifier>
</macOptions>
<windowsOptions>
<dirChooser>true</dirChooser>
<menuGroup>misc</menuGroup>
<upgradeUUID>CB11CB66-71B5-42C1-8076-15F1FEDCC22A</upgradeUUID>
</windowsOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>app-bundles-Linux</id>
<activation>
<os>
<family>Unix</family>
</os>
<property>
<name>desktop-package</name>
</property>
</activation>
<build>
<plugins>
<!-- Resource plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>filtering-resources</id>
<goals>
<goal>resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/target/linux/resources</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources/linux</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>net.agilhard.maven.plugins</groupId>
<artifactId>jlink-jpackager-maven-plugin</artifactId>
<configuration>
<name>${package.identifier}</name>
<icon>${project.basedir}/src/main/resources/linux/Open-eCard-App.png</icon>
<resourceDir>${project.basedir}/target/linux/resources</resourceDir>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>app-bundles-win</id>
<activation>
<os>
<family>windows</family>
</os>
<property>
<name>desktop-package</name>
</property>
</activation>
<build>
<plugins>
<!-- Resource plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>filtering-resources</id>
<goals>
<goal>resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources/windows/filtering</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Create .msi installer -->
<plugin>
<groupId>net.agilhard.maven.plugins</groupId>
<artifactId>jlink-jpackager-maven-plugin</artifactId>
<configuration>
<name>${app.identifier}</name>
<icon>${project.basedir}/src/main/resources/windows/Open-eCard-App.ico</icon>
<type>msi</type>
</configuration>
</plugin>
<!-- Create .exe installer -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>create-exe</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>ISCC.exe</executable>
<workingDirectory>${project.basedir}/target</workingDirectory>
<arguments>
<argument>classes/Open-eCard-App.iss</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>app-bundles-mac</id>
<activation>
<os>
<family>mac</family>
</os>
<property>
<name>desktop-package</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>net.agilhard.maven.plugins</groupId>
<artifactId>jlink-jpackager-maven-plugin</artifactId>