Code Monkey home page Code Monkey logo

jnasmartcardio's Introduction

jnasmartcardio

(Previously known as jna2pcsc.) A re-implementation of the javax.smartcardio API. It allows you to communicate to a smart card (at the APDU level) from within Java.

This library allows you to transmit and receive application protocol data units (APDUs) specified by ISO/IEC 7816-3 to a smart card.

This java library is built on top of the WinSCard native library that comes with the operating system (or libpcsclite1 installed on Linux), which in turn communicates to the myriad USB smart card readers, contactless card readers, and dongles.

Protocols built on top of APDUs include PKCS#15 public key authentication, EMV credit/debit transaction, GSM SIM cellular subscriber information, CAC U.S. military identification, Mifare Classic or DESfire transit payment, and any number of custom protocols.

Alternatives

First, if you are using smart cards for authentication and it comes with a PKCS#11 native library (or is supported by opensc-pkcs11), you should probably use the SunPKCS11 KeyStore provider instead of implementing the PKCS#15 client protocol yourself.

Once you have decided on APDU communication, you may wonder why this library exists, given that the JRE already comes with an implementation of javax.smartcardio. What’s wrong with it? There are a couple reasons you might consider switching to a JNA solution:

  • The default smartcardio library in JRE 7 and JRE 8 on 64-bit OS X was compiled incorrectly; bug 7195480. In particular, Terminal.isCardPresent() always returns false, Terminals.list() occasionally causes SIGSEGV, and Terminal.waitForCard(boolean, long) and Terminals.waitForChange(long) don’t wait. Ivan Gerasimov (igerasim) fixed waitForCard, fixed list and isCardPresent, and fixed Card.openLogicalChannel for JRE 7u80, 8u20, and 9.
  • The default smartcardio library only calls SCardEstablishContext once. If the daemon isn’t up yet, then your process will never be able to connect to it again. This is a big problem because in Windows 8, OS X, and new versions of pcscd, the daemon is not started until a reader is plugged in, and it quits when there are no more readers.
  • It’s easier to fix bugs in this project than it is to fix bugs in the libraries that are bundled with the JRE. Anybody can create and comment on issues.

Another implementation of the smartcardio API is intarsys/smartcard-io, which is much more mature than this project. Please consider it. You might choose jnasmartcardio instead because:

  • jnasmartcardio is much smaller and has fewer dependencies than smartcard-io.

Installation

Requires JDK 1.6 or above.

Download the most recent published release from the Maven Central Repository. If you are using maven, you simply add this dependency to your own project’s pom.xml:

<dependency>
	<groupId>io.github.jnasmartcardio</groupId>
	<artifactId>jnasmartcardio</artifactId>
	<version>0.2.7</version>
</dependency>

To build from source, run the following command to compile, jar, and install to your local Maven repository. Don’t forget to also modify your own project’s pom.xml to depend on the same SNAPSHOT version. You may need to learn the Maven version arcana.

mvn install

Once you have jnasmartcardio in your classpath, there are 3 ways to use this smartcard provider instead of the one that is bundled with JRE:

  1. Modify <java_home>/jre/lib/security/java.security; replace security.provider.9=sun.security.smartcardio.SunPCSC with security.provider.9=jnasmartcardio.Smartcardio. Then use TerminalFactory.getDefault().
  2. Create a file override.java.security, then add system property -Djava.security.properties=override.java.security. This should be a file that contains a line like the above. But make sure that you override the same numbered line as the existing SunPCSC in your JRE; otherwise, you may disable some other factory too! Then use TerminalFactory.getDefault()
  3. Explicitly reference the Smartcardio class at compile time. There are a few variations of this:
    • Security.addProvider(new Smartcardio()); TerminalFactory.getInstance("PC/SC", null, Smartcardio.PROVIDER_NAME);
    • Security.insertProviderAt(new Smartcardio(), 1); TerminalFactory.getInstance("PC/SC", null);
    • TerminalFactory.getInstance("PC/SC", null, new Smartcardio());

Once you have a TerminalFactory, you call cardTerminals = factory.terminals();; see javax.smartcardio API javadoc.

Documentation

The javadoc is uploaded to maven. You can see javadoc at javadoc.io

Changelog

See CHANGES.md.

Caveats

This library requires JNA to talk to the native libraries (winscard.dll, libpcsc.so, or PCSC). You can’t use this library if you are writing an applet or are otherwise using a security manager.

Differences from JRE

Some things to keep in mind which are different from JRE:

Generally, all methods will throw a JnaPCSCException if the daemon/service is off (when there are no readers). On Windows 8, the service is stopped immediately when there are no more readers.

TerminalFactory

TerminalFactory.terminals() will (re-)establish connection with the PCSC daemon/service. If the service is not running, terminals() will throw an unchecked exception EstablishContextException.

JnaCardTerminals

JnaCardTerminals owns the SCardContext native handle, and you should call cardTerminals.close() to clean up. Unfortunately, close() does not exist on the base class, so this library also closes it in its finalizer.

To make the implementation simpler, the caller must be able to handle spurious wakeups when calling waitForChange(long). In other words, list(State.CARD_REMOVAL) and list(State.CARD_INSERTION) might both be empty lists after waitForChange returns.

list(State) with CARD_INSERTION/CARD_REMOVAL always reflects the result of the previous waitForChange call. If there was no previous waitForChange call, it returns an empty list; I do not return the current CARD_PRESENT/CARD_ABSENT value as Sun does because this would be inconsistent with the internal waitForChange state.

As well as waking up when a card is inserted/removed, waitForChange will also wake up when a card reader is plugged in/unplugged. However, in Windows 8, when all readers are unplugged the service will immediately exit, so waitForChange will throw an exception instead of returning.

JnaCardTerminal

connect(String protocol) supports exactly the same connection modes as Sun does: T=0, T=1, T=*, and T=DIRECT (T=CL is mentioned in the smartcardio documentation but is not accepted). Unlike Sun, it does not return the same connection when you connect twice.

If the protocol is prepended with EXCLUSIVE; the usual SCARD_SHARE_SHARED mode shall be replaced with SCARD_SHARE_EXCLUSIVE. This allows to use a safely locked reader on Windows 8+ where otherwise a transaction initiated with SCardBeginTransaction (beginExclusive()) would be closed after 5 seconds and SCARD_W_RESET_CARD returned. See this post on MSDN.

JnaCard

beginExclusive() simply calls SCardBeginTransaction. It does not use thread-local storage, as Sun does.

disconnect(boolean reset) did the opposite in Sun’s implementation, which suffered bug 7047033. Ivan Gerasim of Oracle fixed their implementation to match mine in JRE 7u80, 8u20, and 9, although the old behavior can be obtained by -Djdk.smartcard.invertReset=true in JRE 8.

JnaCardChannel

transmit(CommandAPDU command) currently has a response limit of 8192 bytes.

Transmit does the following automatically:

  • Sets the channel number in the class byte (CLA)
  • If T=0 and Lc ≠ 0 and Le ≠ 0, then the Le byte is removed as required.
  • If sw=61xx, then Get Response is automatically sent until the entire response is received.
  • If sw=6cxx, then the request is re-sent with the right Le byte.

However, keep in mind:

  • If T=0, then you must not send a Command APDU with extended Lc/Le. User is responsible for using Envelope commands if needed to turn T=1 commands into T=0 commands.
  • You may perform your own command chaining (e.g. if command is too long to fit in one Command APDU). You must put the command chaining bits in the correct position within the CLA byte, depending on the channel number.
  • If you are using secure messaging, you must put the secure messaging bits in the right position within the CLA byte, depending on the channel number.

License

This code is released under CC0; it is a “universal donor” in the hope that others can find it useful and contribute back.

jnasmartcardio's People

Contributors

ecmrauh avatar martinpaljak avatar sergkh avatar yonran avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jnasmartcardio's Issues

CardTerminals waitForChange is not working as expected

Consider the following code:

try {
TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null, new Smartcardio());
CardTerminals terminals=factory.terminals();
List readers=terminals.list(State.CARD_PRESENT);
if(readers.size()>0){
System.out.println("Card present: "+readers.get(0).isCardPresent());
}
if(readers.isEmpty()){
System.out.println("Reader list is empty, waiting for changes.");
terminals.waitForChange();
}
} catch (CardException ex) {
ex.printStackTrace();
}
System.out.println("Change has been detected.");

If you run the above without any reader, this is the output:
Reader list is empty, waiting for changes.

If you run the above with a reader attached without any card present, the output is:
Reader list is empty, waiting for changes.
Change has been detected.

While it shouldn't be so, because there are no cards present.

At lower level SCardGetStatusChange must be invoked twice to detect differences between calls, but only upper bits are significant, according to PCSC spec.

If you plan to mantain this project (last changes aren't recent), I would ask to fix a few things.

PCSC library loading fails on Mac OS X 10.5.2

Might be irrelevant, since the operating system version is hopelessly out of date, but here goes anyway.

java -version Output:

java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03-384-9M3425)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02-384, mixed mode)

pcsctool works fine.

The exception:

java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: PC/SC, provider: JNA2PCSC, class: io.github.yonran.jna2pcsc.Smartcardio$JnaTerminalFactorySpi)
    at java.security.Provider$Service.newInstance(Provider.java:1240)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:227)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:196)
    at javax.smartcardio.TerminalFactory.getInstance(TerminalFactory.java:265)
    at ch.bluecare.weka.smartcard.JNAPCSCSmartcardReaderImpl.getTerminals(JNAPCSCSmartcardReaderImpl.java:31)
    at ch.bluecare.weka.smartcard.JNAPCSCSmartcardReaderImpl.initialize(JNAPCSCSmartcardReaderImpl.java:38)
    at ch.bluecare.weka.smartcard.CardManager$CardDiscoveryThread.initializeReader(CardManager.java:28)
    at ch.bluecare.weka.smartcard.CardManager$CardDiscoveryThread.<init>(CardManager.java:33)
    at ch.bluecare.weka.smartcard.CardManager.start(CardManager.java:64)
    at ch.bluecare.weka.CardManagerTestTool.main(CardManagerTestTool.java:23)
Caused by: java.lang.UnsatisfiedLinkError: Unable to load library '/System/Library/Frameworks/PCSC.framework/PCSC': Native library (System/Library/Frameworks/PCSC.framework/PCSC) not found in resource path ([file:/Volumes/NO%20NAME/cardreader-osx-testing/cardreader-0.0.1-SNAPSHOT-executable.jar])
    at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:271)
    at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:398)
    at com.sun.jna.Library$Handler.<init>(Library.java:147)
    at com.sun.jna.Native.loadLibrary(Native.java:412)
    at com.sun.jna.Native.loadLibrary(Native.java:391)
    at io.github.yonran.jna2pcsc.Winscard.openLib(Winscard.java:425)
    at io.github.yonran.jna2pcsc.Smartcardio$JnaTerminalFactorySpi.<init>(Smartcardio.java:71)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at java.security.Provider$Service.newInstance(Provider.java:1235)
    ... 9 more
22.10.2013 13:44:22 ch.bluecare.weka.smartcard.CardManager$CardDiscoveryThread run

Layout of the PCSC framework directory:

users-imac:cardreader-osx-testing user$ ls -l /System/Library/Frameworks/PCSC.framework
total 24
lrwxr-xr-x  1 root  wheel   24  4 Nov  2010 CodeResources -> Versions/A/CodeResources
lrwxr-xr-x  1 root  wheel   21  4 Nov  2010 PCSC -> Versions/Current/PCSC
lrwxr-xr-x  1 root  wheel   26  4 Nov  2010 Resources -> Versions/Current/Resources
drwxr-xr-x  4 root  wheel  136  4 Nov  2010 Versions
users-imac:cardreader-osx-testing user$ ls -lR /System/Library/Frameworks/PCSC.framework
total 24
lrwxr-xr-x  1 root  wheel   24  4 Nov  2010 CodeResources -> Versions/A/CodeResources
lrwxr-xr-x  1 root  wheel   21  4 Nov  2010 PCSC -> Versions/Current/PCSC
lrwxr-xr-x  1 root  wheel   26  4 Nov  2010 Resources -> Versions/Current/Resources
drwxr-xr-x  4 root  wheel  136  4 Nov  2010 Versions

/System/Library/Frameworks/PCSC.framework/Versions:
total 8
drwxr-xr-x  6 root  wheel  204  4 Nov  2010 A
lrwxr-xr-x  1 root  wheel    1  4 Nov  2010 Current -> A

/System/Library/Frameworks/PCSC.framework/Versions/A:
total 320
-rw-r--r--  1 root  wheel    1319  4 Okt  2007 CodeResources
-rwxr-xr-x  1 root  wheel  159696 18 Jun  2009 PCSC
drwxr-xr-x  4 root  wheel     136  4 Nov  2010 Resources
drwxr-xr-x  3 root  wheel     102 18 Jun  2009 _CodeSignature

/System/Library/Frameworks/PCSC.framework/Versions/A/Resources:
total 16
-rw-r--r--  1 root  wheel  703 18 Jun  2009 Info.plist
-rw-r--r--  1 root  wheel  461 18 Jun  2009 version.plist

/System/Library/Frameworks/PCSC.framework/Versions/A/_CodeSignature:
total 8
-rw-r--r--  1 root  wheel  1319 18 Jun  2009 CodeResources

JnaCard.transmitControllCommand does not work on OSX.

In OSX, the SCardControl function is actually implemented by the SCardControl132 symbol of PCSC; the SCardControl symbol does not have the correct signature. I missed this detail when writing Winscard.java and will have to add a FunctionMapper just like I use for Windows. A parallel bug was also fixed in Sun’s implementation: JDK-8039319.

This was reported by an emailer.

Examples

Hi,

can you provides some examples how to use the lib? ;-)

greetings
gregor

Invalid handle after reconnect

I'm doing this on OSX:

[junit] SCardConnect(*)
[junit] SCardBeginTransaction()
[junit] SCardDisconnect(false)
[junit] SCardConnect(T=1)
[junit] SCardBeginTransaction()

And get this:

[junit] jnasmartcardio.Smartcardio$JnaPCSCException: SCardTransmit got response 0x80100003 (SCARD_E_INVALID_HANDLE: The supplied handle was invalid.)
[junit]     at jnasmartcardio.Smartcardio.check(Smartcardio.java:924)
[junit]     at jnasmartcardio.Smartcardio.check(Smartcardio.java:915)
[junit]     at jnasmartcardio.Smartcardio.access$000(Smartcardio.java:36)
[junit]     at jnasmartcardio.Smartcardio$JnaCardChannel.transmitRaw(Smartcardio.java:851)
[junit]     at jnasmartcardio.Smartcardio$JnaCardChannel.transmitImpl(Smartcardio.java:764)
[junit]     at jnasmartcardio.Smartcardio$JnaCardChannel.transmit(Smartcardio.java:604)

Compatibility with Apache Commons Daemon / JSVC

The following code works perfectly when calling the JAR directly in console

public static void main(String[] args) throws CardException, GPException, NoSuchAlgorithmException {
		GlobalPlatform gp;
		Card card;
		CardTerminal terminal = TerminalManager.getTheReader(null);
		card = terminal.connect("*");
		card.beginExclusive();
		gp = new GlobalPlatform(card.getBasicChannel());
		gp.select(null);
		byte[] info = gp.getCPLC();
		String cardInfo = HexUtils.encodeHexString_imp(info);
		card.disconnect(true);
		System.out.println("Hexa Card Info: " + cardInfo);
	}

When using JSVC (From Apache Commons Daemon library) to launch the JAR as a daemon, I get a JnaPCSCException (SCardEstablishContext got response 0x8010001d (SCARD_E_NO_SERVICE: The Smart card resource manager is not running.)

Java VM created successfully
Class org/apache/commons/daemon/support/DaemonLoader found
Native methods registered
java_init done
Daemon loading...
Daemon loaded successfully
java_load done
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.commons.daemon.support.DaemonLoader.start(DaemonLoader.java:241)
Caused by: jnasmartcardio.Smartcardio$EstablishContextException: jnasmartcardio.Smartcardio$JnaPCSCException: SCardEstablishContext got response 0x8010001d (SCARD_E_NO_SERVICE: The Smart card resource manager is not running.)
at jnasmartcardio.Smartcardio$JnaTerminalFactorySpi.engineTerminals(Smartcardio.java:81)
at javax.smartcardio.TerminalFactory.terminals(TerminalFactory.java:351)
at apdu4j.TerminalManager.getTheReader(TerminalManager.java:228)
at com.st.simple.card.client.Client.main(Client.java:29)
at com.st.simple.card.client.Client.start(Client.java:58)
... 5 more
Caused by: jnasmartcardio.Smartcardio$JnaPCSCException: SCardEstablishContext got response 0x8010001d (SCARD_E_NO_SERVICE: The Smart card resource manager is not running.)
at jnasmartcardio.Smartcardio.check(Smartcardio.java:960)
at jnasmartcardio.Smartcardio.check(Smartcardio.java:951)
at jnasmartcardio.Smartcardio.access$000(Smartcardio.java:34)
at jnasmartcardio.Smartcardio$JnaTerminalFactorySpi.engineTerminals(Smartcardio.java:79)
... 9 more
Cannot start daemon
java_start failed
remove_pid_file: open /tmp/file.pid: fd=3
Service exit with a return value of 5

The fact that the JAR works directly makes me believe the code is right but something related to permissions is maybe causing the issue. Any ideas?

Remove dead code/document

Could you document, elaborate or remove the dead code at main on WaitForChange.java?

if(true) { ... }
else {
TerminalFactory terminalFactory = TerminalFactory.getDefault();
terminals = terminalFactory.terminals();
}

Unable to establishContext()

Using a yubicard NEO. OSX 10.8.whatever.

Exception in thread "main" io.github.yonran.jna2pcsc.Smartcardio$JnaPCSCException: SCardEstablishContext got response 0x8010001d (SCARD_E_NO_SERVICE: The Smart card resource manager is not running.)

Card.disconnect(boolean reset) does not match JDK implementation

The parameter is “reset - whether to reset the card after disconnecting” according to documentation. This is converted to the SCardDisconnect parameter. I do this:

reset ? SCARD_RESET_CARD : SCARD_LEAVE_CARD

which I think matches intarsys/smartcard-io:

reset ? ICardConnection.MODE_RESET
                : ICardConnection.MODE_LEAVE_CARD

while Sun does the opposite. This is documented in bug 7047033:

reset ? SCARD_LEAVE_CARD : SCARD_RESET_CARD

Either we should switch the logic of the to match the Sun behavior and call it “noReset”, or we should document how our behavior differs from Sun.

Add SCardCancel function

Consider the following scenario:
Reader with card present, after some operations I invoke:
terminal.waitForAbsent(0);

Actually seems ScardCancel operation is not implemented, so i cant cancel the wait to properly interrupt the wait, according to https://pcsclite.alioth.debian.org/api/group__API.html#gaacbbc0c6d6c0cbbeb4f4debf6fbeeee6

This implies the context should be recoverable somehow to use it on the same thread (IIRC, each thread should have its own. Sure @martinpaljak @LudovicRousseau know).

Regards

Fails to build on Mac OS X 10.9

I am not a Java expert. Maybe I am missing something obvious.

$ mvn install
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building jnasmartcardio 0.2.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ jnasmartcardio ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/rousseau/Documents/github/jnasmartcardio/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ jnasmartcardio ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 4 source files to /Users/rousseau/Documents/github/jnasmartcardio/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] /Users/rousseau/Documents/github/jnasmartcardio/src/main/java/jnasmartcardio/Smartcardio.java:[90,79] cannot find symbol
symbol  : class AutoCloseable
location: class jnasmartcardio.Smartcardio
[ERROR] /Users/rousseau/Documents/github/jnasmartcardio/src/main/java/jnasmartcardio/Smartcardio.java:[342,17] method does not override or implement a method from a supertype
[INFO] 2 errors 
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.813s
[INFO] Finished at: Sun Feb 09 17:18:52 CET 2014
[INFO] Final Memory: 10M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project jnasmartcardio: Compilation failure: Compilation failure:
[ERROR] /Users/rousseau/Documents/github/jnasmartcardio/src/main/java/jnasmartcardio/Smartcardio.java:[90,79] cannot find symbol
[ERROR] symbol  : class AutoCloseable
[ERROR] location: class jnasmartcardio.Smartcardio
[ERROR] /Users/rousseau/Documents/github/jnasmartcardio/src/main/java/jnasmartcardio/Smartcardio.java:[342,17] method does not override or implement a method from a supertype
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

I use Java 1.7

$ java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

The full error message (using mvn -X) is:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.866s
[INFO] Finished at: Sun Feb 09 17:21:40 CET 2014
[INFO] Final Memory: 10M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project jnasmartcardio: Compilation failure: Compilation failure:
[ERROR] /Users/rousseau/Documents/github/jnasmartcardio/src/main/java/jnasmartcardio/Smartcardio.java:[90,79] cannot find symbol
[ERROR] symbol  : class AutoCloseable
[ERROR] location: class jnasmartcardio.Smartcardio
[ERROR] /Users/rousseau/Documents/github/jnasmartcardio/src/main/java/jnasmartcardio/Smartcardio.java:[342,17] method does not override or implement a method from a supertype
[ERROR] -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project jnasmartcardio: Compilation failure
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:317)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:152)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:555)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.compiler.CompilationFailureException: Compilation failure
    at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:858)
    at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:106)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
    ... 19 more
[ERROR] 
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

JNA 4.0.0 dependency

I'm trying to integrate jnasmartcardio into an existing project, that already has a dependency on JNA 3.2.5. When using it with this (albeit outdated) version, I get the follwing crash:

java.lang.IllegalStateException: Error creating SCardReaderState
    at jnasmartcardio.Winscard$WinscardLibInfo.createSCardReaderState(Winscard.java:417)
    at jnasmartcardio.Smartcardio$JnaCardTerminals.<init>(Smartcardio.java:123)
    at jnasmartcardio.Smartcardio$JnaTerminalFactorySpi.engineTerminals(Smartcardio.java:87)
    at javax.smartcardio.TerminalFactory.terminals(TerminalFactory.java:332)
[... more trace, irrelevant ...]
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at jnasmartcardio.Winscard$WinscardLibInfo.createSCardReaderState(Winscard.java:409)
    ... 21 more
Caused by: java.lang.NoSuchMethodError: com.sun.jna.Structure.<init>(I)V
    at jnasmartcardio.Winscard$WinscardSCardReaderState.<init>(Winscard.java:123)
    at jnasmartcardio.Winscard$OSXSCardReaderState.<init>(Winscard.java:151)
    ... 26 more

My problem is that I'm working on a maintenance project and currently that I can not easily update JNA to 4.0.0.

As far as I can see, we can just use the ctor com.sun.jna.Structure(Pointer, int align) and pass a null Pointer. I had to replace two invocations and afterwards tested it with 3.2.5 and it seems to work fine (for my use case at least).

Would it be possible to be a bit more conservative in terms of JNA version requirements? Or we could leave the dependency as-is and just modify the constructor invocations, and hope that JNA is more or less backward-compatible.

What do you think?

No longer JDK 1.6 compatible

Does anyone still care about JDK 1.6 compatibility? If so, I should take out my AutoCloseable references. 0.2.1 required JDK 1.7.

Memory leak

When creating new TerminalFactory with following code:
TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null, new jnasmartcardio.Smartcardio());

a ThreadLocal of type com.sun.jna.Structure is also created inside of the Smartcardio object (thanks to creation of SCardReaderState's Pointer object)

The issue is that instantiation of jnasmartcardio.Smartcardio results in memory leak on Tomcat9 server with following error message, after shutting the server down via ./catalina.out stop command:

01-Jul-2020 11:28:34.146 SEVERE [main] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [MyServiceProvider] created a ThreadLocal with key of type [com.sun.jna.Structure$2] (value [com.sun.jna.Structure$2@6cd98a05]) and a value of type [com.sun.jna.Structure.StructureSet] (value [[]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

I cannot access the com.sun.jna package of jnasmartcardio from my own app, so I implemented the Maven dependency directly in my project in pom.xml:

	_<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
	<dependency>
		<groupId>net.java.dev.jna</groupId>
		<artifactId>jna</artifactId>
		<version>5.4.0</version>
	</dependency>_

This allowed me to call com.sun.jna.Memory.disposeAll() inside of destroy() method of my Java Servlet. However, the memory leak still occurs.

OSX 10.10 Yosemite: CardTerminals.waitForChange never returns.

CardTerminals.waitForChange(long) waits forever in OSX 10.10 Yosemite.

CardTerminals.waitForChange(long) uses SCardGetStatusChange to receive a card insertion/removal event. I also use the fake \\?PnP?\Notification reader to receive card reader insertion events. In Windows and Mac, I don’t even bother reading the initial reader state; the PNP notification will return early when there is a reader already plugged in that the application did not know about, and there are no race conditions. However, on Linux this does not work for existing readers; it only works for readers plugged in during the wait call (which I think causes race condition between listing readers and waiting). In OSX 10.10 Yosemite, the Mac acts just like Linux; one must list the readers before waiting.

I will modify the platform check to do the same thing on OSX as Linux.

OSX 10.10 Yosemite: CardTerminal.connect throws JnaPCSCException(SCARD_E_INSUFFICIENT_BUFFER)

CardTerminal.connect fails in OSX 10.10 Yosemite. Detailed description follows.

In the WinSCard API, When supplying pcchReaderLen to SCardStatus, one is supposed to call SCardStatus twice, first to get the length and second to copy the multistring value into szReaderName. In OSX 10.10 Yosemite. there are 2 bugs:

  1. When the buffer is NULL, SCardStatus writes out a length that only includes the strlen of the name. It does give enough space for the 2 NUL characters!
  2. When the buffer is non-NULL, the reader name is written to the buffer, but only a single NUL character is written! (Multistrings should be terminated by an empty string).

Sample C code that fails:

DWORD namesLength;
SCardStatus(..., NULL, &namesLength, ...);
LPTSTR names = malloc(namesLength);
SCardStatus(..., names, &namesLength, ...);  // returns SCARD_E_INSUFFICIENT_BUFFER

I have posted a sample that fails in SCardStatus in OSX 10.10 Yosemite.

In practice, however, one never needs to know all the names of the card reader after connecting to the card; we already had the unique reader name that was needed to connect. So I will take out the calls to get the reader name.

Allow user to re-initialize CardTerminals when the service is off.

Currently, creating the TerminalFactory already creates a final SCardContext, and there is no way to recreate the SCardContext when the service/daemon shuts down. This is a problem on Windows 8 and OS X, which shut down the service when there are no readers attached.

I think that each call to TerminalFactory.terminals() should SCardEstablishContext so that each JnaCardTerminals object should have its own final SCardContext. That way, the user can call terminals() to re-establish a connection to the service after JnaPCSCException(SCARD_E_NO_READERS_AVAILABLE) or JnaPCSCException(SCARD_E_NO_SERVICE). It will still be painful to users of the library because they have to handle these exceptions and manually reconnect.

An alternative is to transparently establish a new SCardContext as needed without the user knowing. This will require changing all the final SCardContext variables into AtomicReference<SCardContext> instead. Also, what will CardTerminals.waitForChange() do? Should it automatically start polling every 1s waiting for the service to come back up?

Not working on Java Android Studio

when I try to connect this with the android app built in android studio, I can not import TerminalFactory, whereas Smartcardio() class is working but without terminalFactory things are not working.

Screen Shot 2022-07-18 at 9 40 32 AM

ThankYou

Maven vs ant vs simpler structure ?

As JNA is distributed through maven by default (so it seems to me) I can understand why it is used here as well. I checked out the source code on a clean osx machine and to build a simple three file project, two screens full of "Downloading" messages appeared . What about bundling the necessary JNA jar and using a simple ant script? Also, what about an Example.java ?

SCARD_E_INVALID_HANDLE on SCardConnect

I am getting the following exception on OS X 10.8 and 10.9, using the latest master:

Caused by: jnasmartcardio.Smartcardio$JnaPCSCException: SCardConnect got response 0xffffffff80100003 (SCARD_E_INVALID_HANDLE: The supplied handle was invalid.)
    at jnasmartcardio.Smartcardio.check(Smartcardio.java:920)
    at jnasmartcardio.Smartcardio.access$100(Smartcardio.java:35)
    at jnasmartcardio.Smartcardio$JnaCardTerminal.connect(Smartcardio.java:421)
    at 

Do you have an idea what might be causing this? I'm calling CardTerminals.waitForChange(0) and then listing the CardReaders that have CARD_INSERTION state, connecting to those cards, and reading a serial number. I'm doing this in an endless loop. The loop, along with the initialization, runs in a background thread.

I see some jnasmartcardio Output on System.out:

 INFO [CardManager$CardDiscoveryThread] (CardManager.java:55) - Background card discovery thread started
DEBUG [CardManager$CardDiscoveryThread] (AbstractSmartcardReader.java:96) - Waiting for changes...
0 -> 6 \\?PnP?\Notification
DEBUG [$CardDiscoveryThread] (AbstractSmartcardReader.java:96) - Waiting for changes...
6 -> 4 \\?PnP?\Notification
12 -> 22 SCM SCR 3310 00 00
 INFO [CardManager$CardDiscoveryThread] (AbstractSmartcardReader.java:100) - Card inserted in terminal: SCM SCR 3310 00 00
 WARN [CardManager$CardDiscoveryThread] (CardManager.java:77) - Failure while waiting for smartcards: jnasmartcardio.Smartcardio$JnaPCSCException: SCardConnect got response 0xffffffff80100003 (SCARD_E_INVALID_HANDLE: The supplied handle was invalid.)
at ...

The output looks a bit suspicious, as the first waitForChanges call completes instantly.
Is there perhaps some problem with PnP notification? I tried setting the boolean member usePnp to false, but the issue still happens. Were there any recent changes that might be causing this behavior?
And last but not least, are there any threading constraints when using jnasmartcardio?

Compilation with JAN 5.0.0 fails

[ERROR] /Users/martin/projects/jnasmartcardio/src/main/java/jnasmartcardio/Winscard.java:[83,78] cannot find symbol
symbol: variable SIZE
location: class com.sun.jna.Pointer

Can't create TerminalFactory on Raspberry Pi

Creating the Smartcardio terminal works on Windows 10, but the same command does not work on the Raspberry Pi (TerminalFactory.getInstance("PC/SC", null, new Smartcardio())).
Using the default factory with javax.smartcardio.TerminalFactory.getDefault() works on both platforms.
Can you interpret the error message below?

java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: PC/SC, provider: JNA2PCSC, class: jnasmartcardio.Smartcardio$JnaTerminalFactorySpi) at
java.security.Provider$Service.newInstance(Provider.java:1617) at
sun.security.jca.GetInstance.getInstance(GetInstance.java:243) at
sun.security.jca.GetInstance.getInstance(GetInstance.java:224) at
javax.smartcardio.TerminalFactory.getInstance(TerminalFactory.java:316) at
com.abc.webnfc.NfcToolsBasedWorker.findCardTerminals(NfcToolsBasedWorker.java:137) at
com.abc.webnfc.NfcToolsBasedWorker.performSetup(NfcToolsBasedWorker.java:105) at
com.abc.webnfc.NfcToolsBasedWorker.run(NfcToolsBasedWorker.java:77) at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at
java.lang.Thread.run(Thread.java:745) Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.sun.jna.Native at
jnasmartcardio.Winscard.openLib(Winscard.java:291) at
jnasmartcardio.Smartcardio$JnaTerminalFactorySpi.(Smartcardio.java:54) at
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at
java.lang.reflect.Constructor.newInstance(Constructor.java:422) at
java.security.Provider$Service.newInstance(Provider.java:1609) ... 9 more

Also, libjna-java is in the newest version: 4.2.2-3. Why is the library trying to use WinSCard on Linux?

Better compatibility with SunPCSC

Those who depend on the features would appreciate the compatibility:
Properties:
sun.security.smartcardio.t0GetResponse
sun.security.smartcardio.t1GetResponse
sun.security.smartcardio.t1StripLe
sun.security.smartcardio.library

SunPCSC also does some self-defence tricks which don't allow certain conditions - like transactions within one application being already done by some other thread (I'm not sure this is correct or sufficient, some other application might have the access and the situation is handled by PC/SC subsystem), some parameter checks etc. Some programming techniques should be enforced, IMHO.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.