feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
298
jdkSrc/jdk8/sun/security/smartcardio/CardImpl.java
Normal file
298
jdkSrc/jdk8/sun/security/smartcardio/CardImpl.java
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.smartcardio;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import javax.smartcardio.*;
|
||||
import static sun.security.smartcardio.PCSC.*;
|
||||
|
||||
/**
|
||||
* Card implementation.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
final class CardImpl extends Card {
|
||||
|
||||
private static enum State { OK, REMOVED, DISCONNECTED };
|
||||
|
||||
// the terminal that created this card
|
||||
private final TerminalImpl terminal;
|
||||
|
||||
// the native SCARDHANDLE
|
||||
final long cardId;
|
||||
|
||||
// atr of this card
|
||||
private final ATR atr;
|
||||
|
||||
// protocol in use, one of SCARD_PROTOCOL_T0 and SCARD_PROTOCOL_T1
|
||||
final int protocol;
|
||||
|
||||
// the basic logical channel (channel 0)
|
||||
private final ChannelImpl basicChannel;
|
||||
|
||||
// state of this card connection
|
||||
private volatile State state;
|
||||
|
||||
// thread holding exclusive access to the card, or null
|
||||
private volatile Thread exclusiveThread;
|
||||
|
||||
// used for platform specific logic
|
||||
private static final boolean isWindows;
|
||||
|
||||
static {
|
||||
final String osName = AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty("os.name"));
|
||||
isWindows = osName.startsWith("Windows");
|
||||
}
|
||||
|
||||
CardImpl(TerminalImpl terminal, String protocol) throws PCSCException {
|
||||
this.terminal = terminal;
|
||||
int sharingMode = SCARD_SHARE_SHARED;
|
||||
int connectProtocol;
|
||||
if (protocol.equals("*")) {
|
||||
connectProtocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
|
||||
} else if (protocol.equalsIgnoreCase("T=0")) {
|
||||
connectProtocol = SCARD_PROTOCOL_T0;
|
||||
} else if (protocol.equalsIgnoreCase("T=1")) {
|
||||
connectProtocol = SCARD_PROTOCOL_T1;
|
||||
} else if (protocol.equalsIgnoreCase("direct")) {
|
||||
// testing
|
||||
|
||||
// MSDN states that the preferred protocol can be zero, but doesn't
|
||||
// specify whether other values are allowed.
|
||||
// pcsc-lite implementation expects the preferred protocol to be non zero.
|
||||
connectProtocol = isWindows ? 0 : SCARD_PROTOCOL_RAW;
|
||||
|
||||
sharingMode = SCARD_SHARE_DIRECT;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported protocol " + protocol);
|
||||
}
|
||||
cardId = SCardConnect(terminal.contextId, terminal.name,
|
||||
sharingMode, connectProtocol);
|
||||
byte[] status = new byte[2];
|
||||
byte[] atrBytes = SCardStatus(cardId, status);
|
||||
atr = new ATR(atrBytes);
|
||||
this.protocol = status[1] & 0xff;
|
||||
basicChannel = new ChannelImpl(this, 0);
|
||||
state = State.OK;
|
||||
}
|
||||
|
||||
void checkState() {
|
||||
State s = state;
|
||||
if (s == State.DISCONNECTED) {
|
||||
throw new IllegalStateException("Card has been disconnected");
|
||||
} else if (s == State.REMOVED) {
|
||||
throw new IllegalStateException("Card has been removed");
|
||||
}
|
||||
}
|
||||
|
||||
boolean isValid() {
|
||||
if (state != State.OK) {
|
||||
return false;
|
||||
}
|
||||
// ping card via SCardStatus
|
||||
try {
|
||||
SCardStatus(cardId, new byte[2]);
|
||||
return true;
|
||||
} catch (PCSCException e) {
|
||||
state = State.REMOVED;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSecurity(String action) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new CardPermission(terminal.name, action));
|
||||
}
|
||||
}
|
||||
|
||||
void handleError(PCSCException e) {
|
||||
if (e.code == SCARD_W_REMOVED_CARD) {
|
||||
state = State.REMOVED;
|
||||
}
|
||||
}
|
||||
|
||||
public ATR getATR() {
|
||||
return atr;
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
switch (protocol) {
|
||||
case SCARD_PROTOCOL_T0:
|
||||
return "T=0";
|
||||
case SCARD_PROTOCOL_T1:
|
||||
return "T=1";
|
||||
default:
|
||||
// should never occur
|
||||
return "Unknown protocol " + protocol;
|
||||
}
|
||||
}
|
||||
|
||||
public CardChannel getBasicChannel() {
|
||||
checkSecurity("getBasicChannel");
|
||||
checkState();
|
||||
return basicChannel;
|
||||
}
|
||||
|
||||
private static int getSW(byte[] b) {
|
||||
if (b.length < 2) {
|
||||
return -1;
|
||||
}
|
||||
int sw1 = b[b.length - 2] & 0xff;
|
||||
int sw2 = b[b.length - 1] & 0xff;
|
||||
return (sw1 << 8) | sw2;
|
||||
}
|
||||
|
||||
private static byte[] commandOpenChannel = new byte[] {0, 0x70, 0, 0, 1};
|
||||
|
||||
public CardChannel openLogicalChannel() throws CardException {
|
||||
checkSecurity("openLogicalChannel");
|
||||
checkState();
|
||||
checkExclusive();
|
||||
try {
|
||||
byte[] response = SCardTransmit
|
||||
(cardId, protocol, commandOpenChannel, 0, commandOpenChannel.length);
|
||||
if ((response.length != 3) || (getSW(response) != 0x9000)) {
|
||||
throw new CardException
|
||||
("openLogicalChannel() failed, card response: "
|
||||
+ PCSC.toString(response));
|
||||
}
|
||||
return new ChannelImpl(this, response[0]);
|
||||
} catch (PCSCException e) {
|
||||
handleError(e);
|
||||
throw new CardException("openLogicalChannel() failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
void checkExclusive() throws CardException {
|
||||
Thread t = exclusiveThread;
|
||||
if (t == null) {
|
||||
return;
|
||||
}
|
||||
if (t != Thread.currentThread()) {
|
||||
throw new CardException("Exclusive access established by another Thread");
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void beginExclusive() throws CardException {
|
||||
checkSecurity("exclusive");
|
||||
checkState();
|
||||
if (exclusiveThread != null) {
|
||||
throw new CardException
|
||||
("Exclusive access has already been assigned to Thread "
|
||||
+ exclusiveThread.getName());
|
||||
}
|
||||
try {
|
||||
SCardBeginTransaction(cardId);
|
||||
} catch (PCSCException e) {
|
||||
handleError(e);
|
||||
throw new CardException("beginExclusive() failed", e);
|
||||
}
|
||||
exclusiveThread = Thread.currentThread();
|
||||
}
|
||||
|
||||
public synchronized void endExclusive() throws CardException {
|
||||
checkState();
|
||||
if (exclusiveThread != Thread.currentThread()) {
|
||||
throw new IllegalStateException
|
||||
("Exclusive access not assigned to current Thread");
|
||||
}
|
||||
try {
|
||||
SCardEndTransaction(cardId, SCARD_LEAVE_CARD);
|
||||
} catch (PCSCException e) {
|
||||
handleError(e);
|
||||
throw new CardException("endExclusive() failed", e);
|
||||
} finally {
|
||||
exclusiveThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] transmitControlCommand(int controlCode, byte[] command)
|
||||
throws CardException {
|
||||
checkSecurity("transmitControl");
|
||||
checkState();
|
||||
checkExclusive();
|
||||
if (command == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
try {
|
||||
byte[] r = SCardControl(cardId, controlCode, command);
|
||||
return r;
|
||||
} catch (PCSCException e) {
|
||||
handleError(e);
|
||||
throw new CardException("transmitControlCommand() failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean invertReset =
|
||||
Boolean.parseBoolean(
|
||||
java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction(
|
||||
"sun.security.smartcardio.invertCardReset", "false")));
|
||||
|
||||
public void disconnect(boolean reset) throws CardException {
|
||||
if (reset) {
|
||||
checkSecurity("reset");
|
||||
}
|
||||
if (state != State.OK) {
|
||||
return;
|
||||
}
|
||||
checkExclusive();
|
||||
// to preserve old behaviour, don't change flag until here
|
||||
if (invertReset) {
|
||||
reset = !reset;
|
||||
}
|
||||
try {
|
||||
SCardDisconnect(cardId, (reset ? SCARD_RESET_CARD : SCARD_LEAVE_CARD));
|
||||
} catch (PCSCException e) {
|
||||
throw new CardException("disconnect() failed", e);
|
||||
} finally {
|
||||
state = State.DISCONNECTED;
|
||||
exclusiveThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "PC/SC card in " + terminal.name
|
||||
+ ", protocol " + getProtocol() + ", state " + state;
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
if (state == State.OK) {
|
||||
state = State.DISCONNECTED;
|
||||
SCardDisconnect(cardId, SCARD_LEAVE_CARD);
|
||||
}
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
294
jdkSrc/jdk8/sun/security/smartcardio/ChannelImpl.java
Normal file
294
jdkSrc/jdk8/sun/security/smartcardio/ChannelImpl.java
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.smartcardio;
|
||||
|
||||
import java.nio.*;
|
||||
import java.security.AccessController;
|
||||
|
||||
import javax.smartcardio.*;
|
||||
|
||||
import static sun.security.smartcardio.PCSC.*;
|
||||
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* CardChannel implementation.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
final class ChannelImpl extends CardChannel {
|
||||
|
||||
// the card this channel is associated with
|
||||
private final CardImpl card;
|
||||
|
||||
// the channel number, 0 for the basic logical channel
|
||||
private final int channel;
|
||||
|
||||
// whether this channel has been closed. only logical channels can be closed
|
||||
private volatile boolean isClosed;
|
||||
|
||||
ChannelImpl(CardImpl card, int channel) {
|
||||
this.card = card;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
void checkClosed() {
|
||||
card.checkState();
|
||||
if (isClosed) {
|
||||
throw new IllegalStateException("Logical channel has been closed");
|
||||
}
|
||||
}
|
||||
|
||||
public Card getCard() {
|
||||
return card;
|
||||
}
|
||||
|
||||
public int getChannelNumber() {
|
||||
checkClosed();
|
||||
return channel;
|
||||
}
|
||||
|
||||
private static void checkManageChannel(byte[] b) {
|
||||
if (b.length < 4) {
|
||||
throw new IllegalArgumentException
|
||||
("Command APDU must be at least 4 bytes long");
|
||||
}
|
||||
if ((b[0] >= 0) && (b[1] == 0x70)) {
|
||||
throw new IllegalArgumentException
|
||||
("Manage channel command not allowed, use openLogicalChannel()");
|
||||
}
|
||||
}
|
||||
|
||||
public ResponseAPDU transmit(CommandAPDU command) throws CardException {
|
||||
checkClosed();
|
||||
card.checkExclusive();
|
||||
byte[] commandBytes = command.getBytes();
|
||||
byte[] responseBytes = doTransmit(commandBytes);
|
||||
return new ResponseAPDU(responseBytes);
|
||||
}
|
||||
|
||||
public int transmit(ByteBuffer command, ByteBuffer response) throws CardException {
|
||||
checkClosed();
|
||||
card.checkExclusive();
|
||||
if ((command == null) || (response == null)) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (response.isReadOnly()) {
|
||||
throw new ReadOnlyBufferException();
|
||||
}
|
||||
if (command == response) {
|
||||
throw new IllegalArgumentException
|
||||
("command and response must not be the same object");
|
||||
}
|
||||
if (response.remaining() < 258) {
|
||||
throw new IllegalArgumentException
|
||||
("Insufficient space in response buffer");
|
||||
}
|
||||
byte[] commandBytes = new byte[command.remaining()];
|
||||
command.get(commandBytes);
|
||||
byte[] responseBytes = doTransmit(commandBytes);
|
||||
response.put(responseBytes);
|
||||
return responseBytes.length;
|
||||
}
|
||||
|
||||
private final static boolean t0GetResponse =
|
||||
getBooleanProperty("sun.security.smartcardio.t0GetResponse", true);
|
||||
|
||||
private final static boolean t1GetResponse =
|
||||
getBooleanProperty("sun.security.smartcardio.t1GetResponse", true);
|
||||
|
||||
private final static boolean t1StripLe =
|
||||
getBooleanProperty("sun.security.smartcardio.t1StripLe", false);
|
||||
|
||||
private static boolean getBooleanProperty(String name, boolean def) {
|
||||
String val = AccessController.doPrivileged(new GetPropertyAction(name));
|
||||
if (val == null) {
|
||||
return def;
|
||||
}
|
||||
if (val.equalsIgnoreCase("true")) {
|
||||
return true;
|
||||
} else if (val.equalsIgnoreCase("false")) {
|
||||
return false;
|
||||
} else {
|
||||
throw new IllegalArgumentException
|
||||
(name + " must be either 'true' or 'false'");
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] concat(byte[] b1, byte[] b2, int n2) {
|
||||
int n1 = b1.length;
|
||||
if ((n1 == 0) && (n2 == b2.length)) {
|
||||
return b2;
|
||||
}
|
||||
byte[] res = new byte[n1 + n2];
|
||||
System.arraycopy(b1, 0, res, 0, n1);
|
||||
System.arraycopy(b2, 0, res, n1, n2);
|
||||
return res;
|
||||
}
|
||||
|
||||
private final static int RESPONSE_ITERATIONS = 256;
|
||||
private final static byte[] B0 = new byte[0];
|
||||
|
||||
private byte[] doTransmit(byte[] command) throws CardException {
|
||||
// note that we modify the 'command' array in some cases, so it must
|
||||
// be a copy of the application provided data.
|
||||
try {
|
||||
checkManageChannel(command);
|
||||
setChannel(command);
|
||||
int n = command.length;
|
||||
boolean t0 = card.protocol == SCARD_PROTOCOL_T0;
|
||||
boolean t1 = card.protocol == SCARD_PROTOCOL_T1;
|
||||
if (t0 && (n >= 7) && (command[4] == 0)) {
|
||||
throw new CardException
|
||||
("Extended length forms not supported for T=0");
|
||||
}
|
||||
if ((t0 || (t1 && t1StripLe)) && (n >= 7)) {
|
||||
int lc = command[4] & 0xff;
|
||||
if (lc != 0) {
|
||||
if (n == lc + 6) {
|
||||
n--;
|
||||
}
|
||||
} else {
|
||||
lc = ((command[5] & 0xff) << 8) | (command[6] & 0xff);
|
||||
if (n == lc + 9) {
|
||||
n -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean getresponse = (t0 && t0GetResponse) || (t1 && t1GetResponse);
|
||||
int k = 0;
|
||||
byte[] result = B0;
|
||||
while (true) {
|
||||
if (++k > RESPONSE_ITERATIONS) {
|
||||
throw new CardException("Number of response iterations" +
|
||||
" exceeded maximum " + RESPONSE_ITERATIONS);
|
||||
}
|
||||
byte[] response = SCardTransmit
|
||||
(card.cardId, card.protocol, command, 0, n);
|
||||
int rn = response.length;
|
||||
if (getresponse && (rn >= 2)) {
|
||||
// see ISO 7816/2005, 5.1.3
|
||||
if ((rn == 2) && (response[0] == 0x6c)) {
|
||||
// Resend command using SW2 as short Le field
|
||||
command[n - 1] = response[1];
|
||||
continue;
|
||||
}
|
||||
if (response[rn - 2] == 0x61) {
|
||||
// Issue a GET RESPONSE command with the same CLA
|
||||
// using SW2 as short Le field
|
||||
if (rn > 2) {
|
||||
result = concat(result, response, rn - 2);
|
||||
}
|
||||
command[1] = (byte)0xC0;
|
||||
command[2] = 0;
|
||||
command[3] = 0;
|
||||
command[4] = response[rn - 1];
|
||||
n = 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
result = concat(result, response, rn);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
} catch (PCSCException e) {
|
||||
card.handleError(e);
|
||||
throw new CardException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getSW(byte[] res) throws CardException {
|
||||
if (res.length < 2) {
|
||||
throw new CardException("Invalid response length: " + res.length);
|
||||
}
|
||||
int sw1 = res[res.length - 2] & 0xff;
|
||||
int sw2 = res[res.length - 1] & 0xff;
|
||||
return (sw1 << 8) | sw2;
|
||||
}
|
||||
|
||||
private static boolean isOK(byte[] res) throws CardException {
|
||||
return (res.length == 2) && (getSW(res) == 0x9000);
|
||||
}
|
||||
|
||||
private void setChannel(byte[] com) {
|
||||
int cla = com[0];
|
||||
if (cla < 0) {
|
||||
// proprietary class format, cannot set or check logical channel
|
||||
// for now, just return
|
||||
return;
|
||||
}
|
||||
// classes 001x xxxx is reserved for future use in ISO, ignore
|
||||
if ((cla & 0xe0) == 0x20) {
|
||||
return;
|
||||
}
|
||||
// see ISO 7816/2005, table 2 and 3
|
||||
if (channel <= 3) {
|
||||
// mask of bits 7, 1, 0 (channel number)
|
||||
// 0xbc == 1011 1100
|
||||
com[0] &= 0xbc;
|
||||
com[0] |= channel;
|
||||
} else if (channel <= 19) {
|
||||
// mask of bits 7, 3, 2, 1, 0 (channel number)
|
||||
// 0xbc == 1011 0000
|
||||
com[0] &= 0xb0;
|
||||
com[0] |= 0x40;
|
||||
com[0] |= (channel - 4);
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported channel number: " + channel);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws CardException {
|
||||
if (getChannelNumber() == 0) {
|
||||
throw new IllegalStateException("Cannot close basic logical channel");
|
||||
}
|
||||
if (isClosed) {
|
||||
return;
|
||||
}
|
||||
card.checkExclusive();
|
||||
try {
|
||||
byte[] com = new byte[] {0x00, 0x70, (byte)0x80, 0};
|
||||
com[3] = (byte)getChannelNumber();
|
||||
setChannel(com);
|
||||
byte[] res = SCardTransmit(card.cardId, card.protocol, com, 0, com.length);
|
||||
if (isOK(res) == false) {
|
||||
throw new CardException("close() failed: " + PCSC.toString(res));
|
||||
}
|
||||
} catch (PCSCException e) {
|
||||
card.handleError(e);
|
||||
throw new CardException("Could not close channel", e);
|
||||
} finally {
|
||||
isClosed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "PC/SC channel " + channel;
|
||||
}
|
||||
|
||||
}
|
||||
187
jdkSrc/jdk8/sun/security/smartcardio/PCSC.java
Normal file
187
jdkSrc/jdk8/sun/security/smartcardio/PCSC.java
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.smartcardio;
|
||||
|
||||
import java.security.AccessController;
|
||||
|
||||
/**
|
||||
* Access to native PC/SC functions and definition of PC/SC constants.
|
||||
* Initialization and platform specific PC/SC constants are handled in
|
||||
* the platform specific superclass.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
final class PCSC extends PlatformPCSC {
|
||||
|
||||
private PCSC() {
|
||||
// no instantiation
|
||||
}
|
||||
|
||||
static void checkAvailable() throws RuntimeException {
|
||||
if (initException != null) {
|
||||
throw new UnsupportedOperationException
|
||||
("PC/SC not available on this platform", initException);
|
||||
}
|
||||
}
|
||||
|
||||
// returns SCARDCONTEXT (contextId)
|
||||
static native long SCardEstablishContext
|
||||
(int scope)
|
||||
throws PCSCException;
|
||||
|
||||
static native String[] SCardListReaders
|
||||
(long contextId)
|
||||
throws PCSCException;
|
||||
|
||||
// returns SCARDHANDLE (cardId)
|
||||
static native long SCardConnect
|
||||
(long contextId, String readerName, int shareMode, int preferredProtocols)
|
||||
throws PCSCException;
|
||||
|
||||
static native byte[] SCardTransmit
|
||||
(long cardId, int protocol, byte[] buf, int ofs, int len)
|
||||
throws PCSCException;
|
||||
|
||||
// returns the ATR of the card, updates status[] with reader state and protocol
|
||||
static native byte[] SCardStatus
|
||||
(long cardId, byte[] status)
|
||||
throws PCSCException;
|
||||
|
||||
static native void SCardDisconnect
|
||||
(long cardId, int disposition)
|
||||
throws PCSCException;
|
||||
|
||||
// returns dwEventState[] of the same size and order as readerNames[]
|
||||
static native int[] SCardGetStatusChange
|
||||
(long contextId, long timeout, int[] currentState, String[] readerNames)
|
||||
throws PCSCException;
|
||||
|
||||
static native void SCardBeginTransaction
|
||||
(long cardId)
|
||||
throws PCSCException;
|
||||
|
||||
static native void SCardEndTransaction
|
||||
(long cardId, int disposition)
|
||||
throws PCSCException;
|
||||
|
||||
static native byte[] SCardControl
|
||||
(long cardId, int controlCode, byte[] sendBuffer)
|
||||
throws PCSCException;
|
||||
|
||||
// PCSC success/error/failure/warning codes
|
||||
final static int SCARD_S_SUCCESS = 0x00000000;
|
||||
final static int SCARD_E_CANCELLED = 0x80100002;
|
||||
final static int SCARD_E_CANT_DISPOSE = 0x8010000E;
|
||||
final static int SCARD_E_INSUFFICIENT_BUFFER = 0x80100008;
|
||||
final static int SCARD_E_INVALID_ATR = 0x80100015;
|
||||
final static int SCARD_E_INVALID_HANDLE = 0x80100003;
|
||||
final static int SCARD_E_INVALID_PARAMETER = 0x80100004;
|
||||
final static int SCARD_E_INVALID_TARGET = 0x80100005;
|
||||
final static int SCARD_E_INVALID_VALUE = 0x80100011;
|
||||
final static int SCARD_E_NO_MEMORY = 0x80100006;
|
||||
final static int SCARD_F_COMM_ERROR = 0x80100013;
|
||||
final static int SCARD_F_INTERNAL_ERROR = 0x80100001;
|
||||
final static int SCARD_F_UNKNOWN_ERROR = 0x80100014;
|
||||
final static int SCARD_F_WAITED_TOO_LONG = 0x80100007;
|
||||
final static int SCARD_E_UNKNOWN_READER = 0x80100009;
|
||||
final static int SCARD_E_TIMEOUT = 0x8010000A;
|
||||
final static int SCARD_E_SHARING_VIOLATION = 0x8010000B;
|
||||
final static int SCARD_E_NO_SMARTCARD = 0x8010000C;
|
||||
final static int SCARD_E_UNKNOWN_CARD = 0x8010000D;
|
||||
final static int SCARD_E_PROTO_MISMATCH = 0x8010000F;
|
||||
final static int SCARD_E_NOT_READY = 0x80100010;
|
||||
final static int SCARD_E_SYSTEM_CANCELLED = 0x80100012;
|
||||
final static int SCARD_E_NOT_TRANSACTED = 0x80100016;
|
||||
final static int SCARD_E_READER_UNAVAILABLE = 0x80100017;
|
||||
|
||||
final static int SCARD_W_UNSUPPORTED_CARD = 0x80100065;
|
||||
final static int SCARD_W_UNRESPONSIVE_CARD = 0x80100066;
|
||||
final static int SCARD_W_UNPOWERED_CARD = 0x80100067;
|
||||
final static int SCARD_W_RESET_CARD = 0x80100068;
|
||||
final static int SCARD_W_REMOVED_CARD = 0x80100069;
|
||||
final static int SCARD_W_INSERTED_CARD = 0x8010006A;
|
||||
|
||||
final static int SCARD_E_UNSUPPORTED_FEATURE = 0x8010001F;
|
||||
final static int SCARD_E_PCI_TOO_SMALL = 0x80100019;
|
||||
final static int SCARD_E_READER_UNSUPPORTED = 0x8010001A;
|
||||
final static int SCARD_E_DUPLICATE_READER = 0x8010001B;
|
||||
final static int SCARD_E_CARD_UNSUPPORTED = 0x8010001C;
|
||||
final static int SCARD_E_NO_SERVICE = 0x8010001D;
|
||||
final static int SCARD_E_SERVICE_STOPPED = 0x8010001E;
|
||||
|
||||
// MS undocumented
|
||||
final static int SCARD_E_NO_READERS_AVAILABLE = 0x8010002E;
|
||||
// std. Windows invalid handle return code, used instead of SCARD code
|
||||
final static int WINDOWS_ERROR_INVALID_HANDLE = 6;
|
||||
final static int WINDOWS_ERROR_INVALID_PARAMETER = 87;
|
||||
|
||||
//
|
||||
final static int SCARD_SCOPE_USER = 0x0000;
|
||||
final static int SCARD_SCOPE_TERMINAL = 0x0001;
|
||||
final static int SCARD_SCOPE_SYSTEM = 0x0002;
|
||||
final static int SCARD_SCOPE_GLOBAL = 0x0003;
|
||||
|
||||
final static int SCARD_SHARE_EXCLUSIVE = 0x0001;
|
||||
final static int SCARD_SHARE_SHARED = 0x0002;
|
||||
final static int SCARD_SHARE_DIRECT = 0x0003;
|
||||
|
||||
final static int SCARD_LEAVE_CARD = 0x0000;
|
||||
final static int SCARD_RESET_CARD = 0x0001;
|
||||
final static int SCARD_UNPOWER_CARD = 0x0002;
|
||||
final static int SCARD_EJECT_CARD = 0x0003;
|
||||
|
||||
final static int SCARD_STATE_UNAWARE = 0x0000;
|
||||
final static int SCARD_STATE_IGNORE = 0x0001;
|
||||
final static int SCARD_STATE_CHANGED = 0x0002;
|
||||
final static int SCARD_STATE_UNKNOWN = 0x0004;
|
||||
final static int SCARD_STATE_UNAVAILABLE = 0x0008;
|
||||
final static int SCARD_STATE_EMPTY = 0x0010;
|
||||
final static int SCARD_STATE_PRESENT = 0x0020;
|
||||
final static int SCARD_STATE_ATRMATCH = 0x0040;
|
||||
final static int SCARD_STATE_EXCLUSIVE = 0x0080;
|
||||
final static int SCARD_STATE_INUSE = 0x0100;
|
||||
final static int SCARD_STATE_MUTE = 0x0200;
|
||||
final static int SCARD_STATE_UNPOWERED = 0x0400;
|
||||
|
||||
final static int TIMEOUT_INFINITE = 0xffffffff;
|
||||
|
||||
private final static char[] hexDigits = "0123456789abcdef".toCharArray();
|
||||
|
||||
public static String toString(byte[] b) {
|
||||
StringBuffer sb = new StringBuffer(b.length * 3);
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
int k = b[i] & 0xff;
|
||||
if (i != 0) {
|
||||
sb.append(':');
|
||||
}
|
||||
sb.append(hexDigits[k >>> 4]);
|
||||
sb.append(hexDigits[k & 0xf]);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
98
jdkSrc/jdk8/sun/security/smartcardio/PCSCException.java
Normal file
98
jdkSrc/jdk8/sun/security/smartcardio/PCSCException.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.smartcardio;
|
||||
|
||||
import static sun.security.smartcardio.PCSC.*;
|
||||
|
||||
/**
|
||||
* Exception for PC/SC errors. The native code portion checks the return value
|
||||
* of the SCard* functions. If it indicates an error, the native code constructs
|
||||
* an instance of this exception, throws it, and returns to Java.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
final class PCSCException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 4181137171979130432L;
|
||||
|
||||
final int code;
|
||||
|
||||
PCSCException(int code) {
|
||||
super(toErrorString(code));
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
private static String toErrorString(int code) {
|
||||
switch (code) {
|
||||
case SCARD_S_SUCCESS : return "SCARD_S_SUCCESS";
|
||||
case SCARD_E_CANCELLED : return "SCARD_E_CANCELLED";
|
||||
case SCARD_E_CANT_DISPOSE : return "SCARD_E_CANT_DISPOSE";
|
||||
case SCARD_E_INSUFFICIENT_BUFFER : return "SCARD_E_INSUFFICIENT_BUFFER";
|
||||
case SCARD_E_INVALID_ATR : return "SCARD_E_INVALID_ATR";
|
||||
case SCARD_E_INVALID_HANDLE : return "SCARD_E_INVALID_HANDLE";
|
||||
case SCARD_E_INVALID_PARAMETER : return "SCARD_E_INVALID_PARAMETER";
|
||||
case SCARD_E_INVALID_TARGET : return "SCARD_E_INVALID_TARGET";
|
||||
case SCARD_E_INVALID_VALUE : return "SCARD_E_INVALID_VALUE";
|
||||
case SCARD_E_NO_MEMORY : return "SCARD_E_NO_MEMORY";
|
||||
case SCARD_F_COMM_ERROR : return "SCARD_F_COMM_ERROR";
|
||||
case SCARD_F_INTERNAL_ERROR : return "SCARD_F_INTERNAL_ERROR";
|
||||
case SCARD_F_UNKNOWN_ERROR : return "SCARD_F_UNKNOWN_ERROR";
|
||||
case SCARD_F_WAITED_TOO_LONG : return "SCARD_F_WAITED_TOO_LONG";
|
||||
case SCARD_E_UNKNOWN_READER : return "SCARD_E_UNKNOWN_READER";
|
||||
case SCARD_E_TIMEOUT : return "SCARD_E_TIMEOUT";
|
||||
case SCARD_E_SHARING_VIOLATION : return "SCARD_E_SHARING_VIOLATION";
|
||||
case SCARD_E_NO_SMARTCARD : return "SCARD_E_NO_SMARTCARD";
|
||||
case SCARD_E_UNKNOWN_CARD : return "SCARD_E_UNKNOWN_CARD";
|
||||
case SCARD_E_PROTO_MISMATCH : return "SCARD_E_PROTO_MISMATCH";
|
||||
case SCARD_E_NOT_READY : return "SCARD_E_NOT_READY";
|
||||
case SCARD_E_SYSTEM_CANCELLED : return "SCARD_E_SYSTEM_CANCELLED";
|
||||
case SCARD_E_NOT_TRANSACTED : return "SCARD_E_NOT_TRANSACTED";
|
||||
case SCARD_E_READER_UNAVAILABLE : return "SCARD_E_READER_UNAVAILABLE";
|
||||
|
||||
case SCARD_W_UNSUPPORTED_CARD : return "SCARD_W_UNSUPPORTED_CARD";
|
||||
case SCARD_W_UNRESPONSIVE_CARD : return "SCARD_W_UNRESPONSIVE_CARD";
|
||||
case SCARD_W_UNPOWERED_CARD : return "SCARD_W_UNPOWERED_CARD";
|
||||
case SCARD_W_RESET_CARD : return "SCARD_W_RESET_CARD";
|
||||
case SCARD_W_REMOVED_CARD : return "SCARD_W_REMOVED_CARD";
|
||||
case SCARD_W_INSERTED_CARD : return "SCARD_W_INSERTED_CARD";
|
||||
|
||||
case SCARD_E_UNSUPPORTED_FEATURE : return "SCARD_E_UNSUPPORTED_FEATURE";
|
||||
case SCARD_E_PCI_TOO_SMALL : return "SCARD_E_PCI_TOO_SMALL";
|
||||
case SCARD_E_READER_UNSUPPORTED : return "SCARD_E_READER_UNSUPPORTED";
|
||||
case SCARD_E_DUPLICATE_READER : return "SCARD_E_DUPLICATE_READER";
|
||||
case SCARD_E_CARD_UNSUPPORTED : return "SCARD_E_CARD_UNSUPPORTED";
|
||||
case SCARD_E_NO_SERVICE : return "SCARD_E_NO_SERVICE";
|
||||
case SCARD_E_SERVICE_STOPPED : return "SCARD_E_SERVICE_STOPPED";
|
||||
|
||||
case SCARD_E_NO_READERS_AVAILABLE: return "SCARD_E_NO_READERS_AVAILABLE";
|
||||
case WINDOWS_ERROR_INVALID_HANDLE: return "WINDOWS_ERROR_INVALID_HANDLE";
|
||||
case WINDOWS_ERROR_INVALID_PARAMETER: return "WINDOWS_ERROR_INVALID_PARAMETER";
|
||||
|
||||
default: return "Unknown error 0x" + Integer.toHexString(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
267
jdkSrc/jdk8/sun/security/smartcardio/PCSCTerminals.java
Normal file
267
jdkSrc/jdk8/sun/security/smartcardio/PCSCTerminals.java
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.smartcardio;
|
||||
|
||||
import java.util.*;
|
||||
import java.lang.ref.*;
|
||||
|
||||
import javax.smartcardio.*;
|
||||
import static javax.smartcardio.CardTerminals.State.*;
|
||||
|
||||
import static sun.security.smartcardio.PCSC.*;
|
||||
|
||||
/**
|
||||
* TerminalFactorySpi implementation class.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
final class PCSCTerminals extends CardTerminals {
|
||||
|
||||
// SCARDCONTEXT, currently shared between all threads/terminals
|
||||
private static long contextId;
|
||||
|
||||
// terminal state used by waitForCard()
|
||||
private Map<String,ReaderState> stateMap;
|
||||
|
||||
PCSCTerminals() {
|
||||
// empty
|
||||
}
|
||||
|
||||
static synchronized void initContext() throws PCSCException {
|
||||
if (contextId == 0) {
|
||||
contextId = SCardEstablishContext(SCARD_SCOPE_USER);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<String,Reference<TerminalImpl>> terminals
|
||||
= new HashMap<String,Reference<TerminalImpl>>();
|
||||
|
||||
private static synchronized TerminalImpl implGetTerminal(String name) {
|
||||
Reference<TerminalImpl> ref = terminals.get(name);
|
||||
TerminalImpl terminal = (ref != null) ? ref.get() : null;
|
||||
if (terminal != null) {
|
||||
return terminal;
|
||||
}
|
||||
terminal = new TerminalImpl(contextId, name);
|
||||
terminals.put(name, new WeakReference<TerminalImpl>(terminal));
|
||||
return terminal;
|
||||
|
||||
}
|
||||
|
||||
public synchronized List<CardTerminal> list(State state) throws CardException {
|
||||
if (state == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
try {
|
||||
String[] readerNames = SCardListReaders(contextId);
|
||||
List<CardTerminal> list = new ArrayList<CardTerminal>(readerNames.length);
|
||||
if (stateMap == null) {
|
||||
// If waitForChange() has never been called, treat event
|
||||
// queries as status queries.
|
||||
if (state == CARD_INSERTION) {
|
||||
state = CARD_PRESENT;
|
||||
} else if (state == CARD_REMOVAL) {
|
||||
state = CARD_ABSENT;
|
||||
}
|
||||
}
|
||||
for (String readerName : readerNames) {
|
||||
CardTerminal terminal = implGetTerminal(readerName);
|
||||
ReaderState readerState;
|
||||
switch (state) {
|
||||
case ALL:
|
||||
list.add(terminal);
|
||||
break;
|
||||
case CARD_PRESENT:
|
||||
if (terminal.isCardPresent()) {
|
||||
list.add(terminal);
|
||||
}
|
||||
break;
|
||||
case CARD_ABSENT:
|
||||
if (terminal.isCardPresent() == false) {
|
||||
list.add(terminal);
|
||||
}
|
||||
break;
|
||||
case CARD_INSERTION:
|
||||
readerState = stateMap.get(readerName);
|
||||
if ((readerState != null) && readerState.isInsertion()) {
|
||||
list.add(terminal);
|
||||
}
|
||||
break;
|
||||
case CARD_REMOVAL:
|
||||
readerState = stateMap.get(readerName);
|
||||
if ((readerState != null) && readerState.isRemoval()) {
|
||||
list.add(terminal);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new CardException("Unknown state: " + state);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
} catch (PCSCException e) {
|
||||
throw new CardException("list() failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ReaderState {
|
||||
private int current, previous;
|
||||
ReaderState() {
|
||||
current = SCARD_STATE_UNAWARE;
|
||||
previous = SCARD_STATE_UNAWARE;
|
||||
}
|
||||
int get() {
|
||||
return current;
|
||||
}
|
||||
void update(int newState) {
|
||||
previous = current;
|
||||
current = newState;
|
||||
}
|
||||
boolean isInsertion() {
|
||||
return !present(previous) && present(current);
|
||||
}
|
||||
boolean isRemoval() {
|
||||
return present(previous) && !present(current);
|
||||
}
|
||||
static boolean present(int state) {
|
||||
return (state & SCARD_STATE_PRESENT) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean waitForChange(long timeout) throws CardException {
|
||||
if (timeout < 0) {
|
||||
throw new IllegalArgumentException
|
||||
("Timeout must not be negative: " + timeout);
|
||||
}
|
||||
if (stateMap == null) {
|
||||
// We need to initialize the state database.
|
||||
// Do that with a recursive call, which will return immediately
|
||||
// because we pass SCARD_STATE_UNAWARE.
|
||||
// After that, proceed with the real call.
|
||||
stateMap = new HashMap<String,ReaderState>();
|
||||
waitForChange(0);
|
||||
}
|
||||
if (timeout == 0) {
|
||||
timeout = TIMEOUT_INFINITE;
|
||||
}
|
||||
try {
|
||||
String[] readerNames = SCardListReaders(contextId);
|
||||
int n = readerNames.length;
|
||||
if (n == 0) {
|
||||
throw new IllegalStateException("No terminals available");
|
||||
}
|
||||
int[] status = new int[n];
|
||||
ReaderState[] readerStates = new ReaderState[n];
|
||||
for (int i = 0; i < readerNames.length; i++) {
|
||||
String name = readerNames[i];
|
||||
ReaderState state = stateMap.get(name);
|
||||
if (state == null) {
|
||||
state = new ReaderState();
|
||||
}
|
||||
readerStates[i] = state;
|
||||
status[i] = state.get();
|
||||
}
|
||||
status = SCardGetStatusChange(contextId, timeout, status, readerNames);
|
||||
stateMap.clear(); // remove any readers that are no longer available
|
||||
for (int i = 0; i < n; i++) {
|
||||
ReaderState state = readerStates[i];
|
||||
state.update(status[i]);
|
||||
stateMap.put(readerNames[i], state);
|
||||
}
|
||||
return true;
|
||||
} catch (PCSCException e) {
|
||||
if (e.code == SCARD_E_TIMEOUT) {
|
||||
return false;
|
||||
} else {
|
||||
throw new CardException("waitForChange() failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static List<CardTerminal> waitForCards(List<? extends CardTerminal> terminals,
|
||||
long timeout, boolean wantPresent) throws CardException {
|
||||
// the argument sanity checks are performed in
|
||||
// javax.smartcardio.TerminalFactory or TerminalImpl
|
||||
|
||||
long thisTimeout;
|
||||
if (timeout == 0) {
|
||||
timeout = TIMEOUT_INFINITE;
|
||||
thisTimeout = TIMEOUT_INFINITE;
|
||||
} else {
|
||||
// if timeout is not infinite, do the initial call that retrieves
|
||||
// the status with a 0 timeout. Otherwise, we might get incorrect
|
||||
// timeout exceptions (seen on Solaris with PC/SC shim)
|
||||
thisTimeout = 0;
|
||||
}
|
||||
|
||||
String[] names = new String[terminals.size()];
|
||||
int i = 0;
|
||||
for (CardTerminal terminal : terminals) {
|
||||
if (terminal instanceof TerminalImpl == false) {
|
||||
throw new IllegalArgumentException
|
||||
("Invalid terminal type: " + terminal.getClass().getName());
|
||||
}
|
||||
TerminalImpl impl = (TerminalImpl)terminal;
|
||||
names[i++] = impl.name;
|
||||
}
|
||||
|
||||
int[] status = new int[names.length];
|
||||
Arrays.fill(status, SCARD_STATE_UNAWARE);
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
// note that we pass "timeout" on each native PC/SC call
|
||||
// that means that if we end up making multiple (more than 2)
|
||||
// calls, we might wait too long.
|
||||
// for now assume that is unlikely and not a problem.
|
||||
status = SCardGetStatusChange(contextId, thisTimeout, status, names);
|
||||
thisTimeout = timeout;
|
||||
|
||||
List<CardTerminal> results = null;
|
||||
for (i = 0; i < names.length; i++) {
|
||||
boolean nowPresent = (status[i] & SCARD_STATE_PRESENT) != 0;
|
||||
if (nowPresent == wantPresent) {
|
||||
if (results == null) {
|
||||
results = new ArrayList<CardTerminal>();
|
||||
}
|
||||
results.add(implGetTerminal(names[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (results != null) {
|
||||
return Collections.unmodifiableList(results);
|
||||
}
|
||||
}
|
||||
} catch (PCSCException e) {
|
||||
if (e.code == SCARD_E_TIMEOUT) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
throw new CardException("waitForCard() failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
72
jdkSrc/jdk8/sun/security/smartcardio/PlatformPCSC.java
Normal file
72
jdkSrc/jdk8/sun/security/smartcardio/PlatformPCSC.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.smartcardio;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
// Platform specific code and constants
|
||||
class PlatformPCSC {
|
||||
|
||||
static final Throwable initException;
|
||||
|
||||
PlatformPCSC() {
|
||||
// empty
|
||||
}
|
||||
|
||||
static {
|
||||
initException = loadLibrary();
|
||||
}
|
||||
|
||||
private static Throwable loadLibrary() {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("j2pcsc");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return null;
|
||||
} catch (Throwable e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
// PCSC constants defined differently under Windows and MUSCLE
|
||||
// Windows version
|
||||
final static int SCARD_PROTOCOL_T0 = 0x0001;
|
||||
final static int SCARD_PROTOCOL_T1 = 0x0002;
|
||||
final static int SCARD_PROTOCOL_RAW = 0x10000;
|
||||
|
||||
final static int SCARD_UNKNOWN = 0x0000;
|
||||
final static int SCARD_ABSENT = 0x0001;
|
||||
final static int SCARD_PRESENT = 0x0002;
|
||||
final static int SCARD_SWALLOWED = 0x0003;
|
||||
final static int SCARD_POWERED = 0x0004;
|
||||
final static int SCARD_NEGOTIABLE = 0x0005;
|
||||
final static int SCARD_SPECIFIC = 0x0006;
|
||||
|
||||
}
|
||||
71
jdkSrc/jdk8/sun/security/smartcardio/SunPCSC.java
Normal file
71
jdkSrc/jdk8/sun/security/smartcardio/SunPCSC.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.smartcardio;
|
||||
|
||||
import java.security.*;
|
||||
|
||||
import javax.smartcardio.*;
|
||||
|
||||
/**
|
||||
* Provider object for PC/SC.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
public final class SunPCSC extends Provider {
|
||||
|
||||
private static final long serialVersionUID = 6168388284028876579L;
|
||||
|
||||
public SunPCSC() {
|
||||
super("SunPCSC", 1.8d, "Sun PC/SC provider");
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
put("TerminalFactory.PC/SC", "sun.security.smartcardio.SunPCSC$Factory");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static final class Factory extends TerminalFactorySpi {
|
||||
public Factory(Object obj) throws PCSCException {
|
||||
if (obj != null) {
|
||||
throw new IllegalArgumentException
|
||||
("SunPCSC factory does not use parameters");
|
||||
}
|
||||
// make sure PCSC is available and that we can obtain a context
|
||||
PCSC.checkAvailable();
|
||||
PCSCTerminals.initContext();
|
||||
}
|
||||
/**
|
||||
* Returns the available readers.
|
||||
* This must be a new object for each call.
|
||||
*/
|
||||
protected CardTerminals engineTerminals() {
|
||||
return new PCSCTerminals();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
146
jdkSrc/jdk8/sun/security/smartcardio/TerminalImpl.java
Normal file
146
jdkSrc/jdk8/sun/security/smartcardio/TerminalImpl.java
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.smartcardio;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.smartcardio.*;
|
||||
|
||||
import static sun.security.smartcardio.PCSC.*;
|
||||
|
||||
/**
|
||||
* CardTerminal implementation.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
final class TerminalImpl extends CardTerminal {
|
||||
|
||||
// native SCARDCONTEXT
|
||||
final long contextId;
|
||||
|
||||
// the name of this terminal (native PC/SC name)
|
||||
final String name;
|
||||
|
||||
private CardImpl card;
|
||||
|
||||
TerminalImpl(long contextId, String name) {
|
||||
this.contextId = contextId;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public synchronized Card connect(String protocol) throws CardException {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new CardPermission(name, "connect"));
|
||||
}
|
||||
if (card != null) {
|
||||
if (card.isValid()) {
|
||||
String cardProto = card.getProtocol();
|
||||
if (protocol.equals("*") || protocol.equalsIgnoreCase(cardProto)) {
|
||||
return card;
|
||||
} else {
|
||||
throw new CardException("Cannot connect using " + protocol
|
||||
+ ", connection already established using " + cardProto);
|
||||
}
|
||||
} else {
|
||||
card = null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
card = new CardImpl(this, protocol);
|
||||
return card;
|
||||
} catch (PCSCException e) {
|
||||
if (e.code == SCARD_W_REMOVED_CARD || e.code == SCARD_E_NO_SMARTCARD) {
|
||||
throw new CardNotPresentException("No card present", e);
|
||||
} else {
|
||||
throw new CardException("connect() failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCardPresent() throws CardException {
|
||||
try {
|
||||
int[] status = SCardGetStatusChange(contextId, 0,
|
||||
new int[] {SCARD_STATE_UNAWARE}, new String[] {name});
|
||||
return (status[0] & SCARD_STATE_PRESENT) != 0;
|
||||
} catch (PCSCException e) {
|
||||
throw new CardException("isCardPresent() failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean waitForCard(boolean wantPresent, long timeout) throws CardException {
|
||||
if (timeout < 0) {
|
||||
throw new IllegalArgumentException("timeout must not be negative");
|
||||
}
|
||||
if (timeout == 0) {
|
||||
timeout = TIMEOUT_INFINITE;
|
||||
}
|
||||
int[] status = new int[] {SCARD_STATE_UNAWARE};
|
||||
String[] readers = new String[] {name};
|
||||
try {
|
||||
// check if card status already matches
|
||||
status = SCardGetStatusChange(contextId, 0, status, readers);
|
||||
boolean present = (status[0] & SCARD_STATE_PRESENT) != 0;
|
||||
if (wantPresent == present) {
|
||||
return true;
|
||||
}
|
||||
// no match, wait (until timeout expires)
|
||||
long end = System.currentTimeMillis() + timeout;
|
||||
while (wantPresent != present && timeout != 0) {
|
||||
// set remaining timeout
|
||||
if (timeout != TIMEOUT_INFINITE) {
|
||||
timeout = Math.max(end - System.currentTimeMillis(), 0l);
|
||||
}
|
||||
status = SCardGetStatusChange(contextId, timeout, status, readers);
|
||||
present = (status[0] & SCARD_STATE_PRESENT) != 0;
|
||||
}
|
||||
return wantPresent == present;
|
||||
} catch (PCSCException e) {
|
||||
if (e.code == SCARD_E_TIMEOUT) {
|
||||
return false;
|
||||
} else {
|
||||
throw new CardException("waitForCard() failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean waitForCardPresent(long timeout) throws CardException {
|
||||
return waitForCard(true, timeout);
|
||||
}
|
||||
|
||||
public boolean waitForCardAbsent(long timeout) throws CardException {
|
||||
return waitForCard(false, timeout);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "PC/SC terminal " + name;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user