Skip to content

Commit

Permalink
Merge pull request #25 from fidesmo/feature-trace-logging
Browse files Browse the repository at this point in the history
Add logging apdu traces
  • Loading branch information
slomo committed Nov 4, 2015
2 parents 0237d34 + 018a970 commit 5b1d301
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 86 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies {
compile gradleApi()
compile localGroovy()
compile 'com.fidesmo:gradle-javacard:0.2.4'
compile 'com.fidesmo:sec-client-core:0.0.5'
compile 'com.fidesmo:sec-client-core:0.1.26'
compile 'io.github.jnasmartcardio:jnasmartcardio:0.2.4'
testCompile 'junit:junit:4.11'
testCompile 'org.hamcrest:hamcrest-all:1.3'
Expand Down

This file was deleted.

32 changes: 9 additions & 23 deletions src/main/groovy/com/fidesmo/gradle/plugin/OperationTask.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@ import org.gradle.api.Project
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException

import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

import retrofit.*
import retrofit.RequestInterceptor.RequestFacade

import com.fidesmo.sec.client.RetrofitSecClient
import com.fidesmo.sec.client.OperationClient
import com.fidesmo.sec.client.OperationClientImpl
import com.fidesmo.sec.client.ClientCallback
import com.fidesmo.sec.transceivers.Transceiver

class OperationTask extends FidesmoBaseTask {

Expand All @@ -38,28 +36,16 @@ class OperationTask extends FidesmoBaseTask {
}

def executeOperation(UUID operationId) {
logger.info("Starting fidesmo sec-client to execute operation '${operationId}'")
def latch = new CountDownLatch(1)
def client = OperationClient.getInstance(

// execute operation by implementing sec-client flow
def client = (new OperationClientImpl()).get(
operationId,
new JnasmartcardioTransceiver(),
new ClientCallback() {
void success() {
latch.countDown()
}
void failure(String message) {
throw new GradleException("Writing to fidesmo card failed with: '${message}'")
}
},
RetrofitSecClient.getClient()
(Transceiver) new SmartcardioTransceiver(),
RetrofitSecClient.client
)
client.transceive().toBlocking().last()

client.transceive()

if (! latch.await(operationTimeout, TimeUnit.SECONDS)) {
throw new GradleException('Time out while writing to fidesmo card')
}

// check operation result by querying the status service
int maxRetries = 9
for(int i = 0; i <= maxRetries; i ++) { // try ten times
try {
Expand Down
89 changes: 89 additions & 0 deletions src/main/java/com/fidesmo/gradle/plugin/LoggingCard.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright 2015 Fidesmo AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.fidesmo.gradle.plugin;

import java.io.IOException;
import java.util.List;
import java.util.ArrayList;

import com.fidesmo.sec.utils.Hex;
import nordpol.IsoCard;
import nordpol.OnCardErrorListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Wrap an IsoCard so that all transmitted APDUs are logged */

public class LoggingCard implements IsoCard {

IsoCard underlying;
Logger logger;

public LoggingCard(IsoCard underlying) {
this.underlying = underlying;
this.logger = LoggerFactory.getLogger("transaction-trace");
}

public void addOnCardErrorListener(OnCardErrorListener listener) {
underlying.addOnCardErrorListener(listener);
}

public void removeOnCardErrorListener(OnCardErrorListener listener) {
underlying.removeOnCardErrorListener(listener);
}

public boolean isConnected() {
return underlying.isConnected();
}

public void connect() throws IOException {
underlying.connect();
}

public void close() throws IOException {
underlying.close();
}

public int getTimeout() {
return underlying.getTimeout();
}

public void setTimeout(int t) {
underlying.setTimeout(t);
}

public int getMaxTransceiveLength() throws IOException {
return underlying.getMaxTransceiveLength();
}

public byte[] transceive(byte[] command) throws IOException {
logger.info("Send to card: " + Hex.encodeHex(command));
byte[] response = underlying.transceive(command);
logger.info("Received from card: " + Hex.encodeHex(response));
return response;
}

public List<byte[]> transceive(List<byte[]> commands) throws IOException {
List<byte[]> responses = new ArrayList<byte[]>(commands.size());
for (byte[] command: commands) {
responses.add(transceive(command));
}
return responses;
}
}
98 changes: 98 additions & 0 deletions src/main/java/com/fidesmo/gradle/plugin/SmartcardioCard.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright 2015 Fidesmo AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.fidesmo.gradle.plugin;

import java.io.IOException;
import java.util.List;
import java.util.ArrayList;

import javax.smartcardio.Card;
import javax.smartcardio.CardException;
import javax.smartcardio.CommandAPDU;

import nordpol.IsoCard;
import nordpol.OnCardErrorListener;

public class SmartcardioCard implements IsoCard {

private Card card;
private boolean openFlag = false;
private int timeout = 15;
private List<OnCardErrorListener> listeners = new ArrayList<OnCardErrorListener>();

public SmartcardioCard(Card card) {
this.card = card;
}

public void addOnCardErrorListener(OnCardErrorListener listener) {
listeners.add(listener);
}

public void removeOnCardErrorListener(OnCardErrorListener listener) {
listeners.remove(listener);
}

public boolean isConnected() {
return openFlag;
}

public void connect() {
openFlag = true;
}

public void close() throws IOException {
try {
card.disconnect(false);
openFlag = false;
} catch (CardException e) {
throw new IOException("Couldn't close card", e);
}
}

public int getTimeout() {
return timeout;
}

public void setTimeout(int t) {
timeout = t;
}

public int getMaxTransceiveLength() {
return 261;
}

public byte[] transceive(byte[] command) throws IOException {
try {
return card
.getBasicChannel()
.transmit(new CommandAPDU(command))
.getBytes();
} catch (CardException e) {
throw new IOException("Couldn't close card", e);
}
}

public List<byte[]> transceive(List<byte[]> commands) throws IOException {
List<byte[]> responses = new ArrayList<byte[]>(commands.size());
for (byte[] command: commands) {
responses.add(transceive(command));
}
return responses;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2015 Fidesmo AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.fidesmo.gradle.plugin;

import java.io.IOException;
import java.util.List;
import java.security.NoSuchAlgorithmException;
import javax.smartcardio.TerminalFactory;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CardTerminals;
import javax.smartcardio.CardException;

import jnasmartcardio.Smartcardio;
import rx.Observable;

import com.fidesmo.sec.transceivers.Transceiver;
import nordpol.IsoCard;


/** Transceiver implementation using the javax.smartcardio package.
*
* This transceiver uses the jnasmartcardio package instead of the
* default implementation.
*/
public class SmartcardioTransceiver implements Transceiver {

public Observable<IsoCard> getCard() {
try {
TerminalFactory factory =
TerminalFactory.getInstance("PC/SC",null, new Smartcardio());
List<CardTerminal> terminalsWithCard =
factory.terminals().list(CardTerminals.State.CARD_PRESENT);

if (terminalsWithCard.size() == 0) {
if (factory.terminals().list().size() == 0) {
return Observable.error(new IOException("No terminals found"));
} else {
return Observable.error(new IOException("No card found"));
}
}

return Observable
.just((IsoCard) new LoggingCard(new SmartcardioCard(terminalsWithCard
.get(0)
.connect("*"))));
} catch (NoSuchAlgorithmException e) {
return Observable.error(new IOException("Error with jnassmartcardio", e));
} catch (CardException e) {
return Observable.error(new IOException("Unable to get Smartcard", e));
}
}
}

0 comments on commit 5b1d301

Please sign in to comment.