use of org.openecard.common.ThreadTerminateException in project open-ecard by ecsec.
the class ChipGateway method processCertificatesRequest.
private CommandType processCertificatesRequest(final ListCertificatesRequestType certReq) throws ConnectionError, JsonProcessingException, InvalidRedirectUrlException, ChipGatewayDataError {
// check if we have been interrupted
checkProcessCancelled();
BigInteger waitSecondsBig = certReq.getMaxWaitSeconds();
long waitMillis = getWaitMillis(waitSecondsBig);
// run the actual stuff in the background, so we can wait and terminate if needed
FutureTask<ListCertificatesResponseType> action = new FutureTask<>(new Callable<ListCertificatesResponseType>() {
@Override
public ListCertificatesResponseType call() throws Exception {
ListCertificatesResponseType certResp = new ListCertificatesResponseType();
certResp.setSessionIdentifier(sessionId);
char[] pin = null;
try {
pin = getPin(certReq.getPIN());
byte[] slotHandle = certReq.getSlotHandle();
ListCertificates helper = new ListCertificates(tokenCache, slotHandle, certReq.getCertificateFilter(), pin);
List<CertificateInfoType> certInfos = helper.getCertificates();
certResp.getCertificateInfo().addAll(certInfos);
certResp.setResult(ChipGatewayStatusCodes.OK);
return certResp;
} finally {
if (pin != null) {
Arrays.fill(pin, ' ');
}
}
}
});
Thread t = new Thread(action, "CertificatesRequest-Task-" + TASK_THREAD_NUM.getAndIncrement());
t.setDaemon(true);
t.start();
ListCertificatesResponseType certResp = new ListCertificatesResponseType();
certResp.setSessionIdentifier(sessionId);
try {
// wait for thread to finish
certResp = action.get(waitMillis, TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
LOG.info("Background task took longer than the timeout value permitted.", ex);
// cancel task
action.cancel(true);
// wait for task to finish, so the SC stack can not get confused
try {
t.join();
certResp.setResult(ChipGatewayStatusCodes.TIMEOUT);
} catch (InterruptedException ignore) {
// send stop message
certResp.setResult(ChipGatewayStatusCodes.STOPPED);
}
} catch (ExecutionException ex) {
LOG.error("Background task produced an exception.", ex);
Throwable cause = ex.getCause();
if (cause instanceof RemotePinException) {
LOG.error("Error getting encrypted PIN.", ex);
certResp.setResult(ChipGatewayStatusCodes.INCORRECT_PARAMETER);
} else if (cause instanceof ParameterInvalid) {
LOG.error("Error while processing the certificate filter parameters.", ex);
certResp.setResult(ChipGatewayStatusCodes.INCORRECT_PARAMETER);
} else if (cause instanceof SlotHandleInvalid) {
LOG.error("No token for the given slot handle found.", cause);
certResp.setResult(ChipGatewayStatusCodes.UNKNOWN_SLOT);
} else if (cause instanceof NoSuchDid) {
LOG.error("DID does not exist.", cause);
certResp.setResult(ChipGatewayStatusCodes.UNKNOWN_DID);
} else if (cause instanceof SecurityConditionUnsatisfiable) {
LOG.error("DID can not be authenticated.", cause);
certResp.setResult(ChipGatewayStatusCodes.SECURITY_NOT_SATISFIED);
} else if (cause instanceof CertificateException) {
LOG.error("Certificate could not be processed.", cause);
certResp.setResult(ChipGatewayStatusCodes.OTHER);
} else if (cause instanceof WSHelper.WSException) {
LOG.error("Unknown error.", cause);
certResp.setResult(ChipGatewayStatusCodes.OTHER);
} else if (cause instanceof ThreadTerminateException) {
LOG.error("Chipgateway process interrupted.", cause);
certResp.setResult(ChipGatewayStatusCodes.STOPPED);
} else {
LOG.error("Unknown error during list certificate operation.", cause);
certResp.setResult(ChipGatewayStatusCodes.OTHER);
}
} catch (InterruptedException ex) {
String msg = "Interrupted while waiting for background task.";
if (LOG.isDebugEnabled()) {
LOG.debug(msg, ex);
} else {
LOG.info(msg);
}
// cancel task
action.cancel(true);
// send stop message
certResp.setResult(ChipGatewayStatusCodes.STOPPED);
}
return sendMessageInterruptableAndCheckTermination(getResource(listCertsUrl), certResp);
}
use of org.openecard.common.ThreadTerminateException in project open-ecard by ecsec.
the class MwSession method findObjects.
private List<Long> findObjects(CK_ATTRIBUTE pTemplate) throws CryptokiException {
try (MiddleWareWrapper.LockedMiddlewareWrapper lmw = mw.lock()) {
lmw.findObjectsInit(sessionHandle, pTemplate, 1);
List<Long> res = lmw.findObjects(sessionHandle);
lmw.findObjectsFinalize(sessionHandle);
return res;
} catch (InterruptedException ex) {
throw new ThreadTerminateException("Thread interrupted while waiting for Middleware lock.", ex);
}
}
use of org.openecard.common.ThreadTerminateException in project open-ecard by ecsec.
the class MiddleWareWrapper method login.
public void login(final long hSession, final long userType, @Nullable byte[] pPin) throws CryptokiException {
ByteBuffer pinBytesTmp = null;
final NativeLong pinLen = new NativeLong(0);
if (pPin != null) {
pinBytesTmp = ByteBuffer.wrap(pPin);
pinLen.setValue(pPin.length);
}
final ByteBuffer pinBytes = pinBytesTmp;
try (LockedObject lo = lockInternal()) {
FutureTask<Void> task = new FutureTask<>(new Callable<Void>() {
@Override
public Void call() throws Exception {
// login to session with pin and usertype
check("C_Login", MiddleWareWrapper.this.lib.C_Login(new NativeLong(hSession), new NativeLong(userType), pinBytes, pinLen), (long) CryptokiLibrary.CKR_OK, (long) CryptokiLibrary.CKR_USER_ALREADY_LOGGED_IN);
return null;
}
});
Thread t = new Thread(task, "Middleware-Login");
t.setDaemon(true);
t.start();
try {
task.get();
} catch (ExecutionException ex) {
Throwable cause = ex.getCause();
if (cause instanceof CryptokiException) {
throw (CryptokiException) cause;
} else if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else {
throw new RuntimeException("Unexpected error received during C_Login call.", cause);
}
} catch (InterruptedException ex) {
task.cancel(true);
LOG.info("Interrupted while waiting for C_Login task.", ex);
throw new ThreadTerminateException("Waiting interrupted by an external thread.", ex);
}
} catch (InterruptedException ex) {
throw new IllegalStateException("Failed to release lock for middleware access.");
}
}
use of org.openecard.common.ThreadTerminateException in project open-ecard by ecsec.
the class ExecutionEngine method process.
/**
* Processes the user consent associated with this instance. <br>
* The following algorithm is used to process the dialog.
* <ol>
* <li>Display the first step.</li>
* <li>Evaluate step result. Break execution on CANCEL.</li>
* <li>Execute step action. Break execution on CANCEL.</li>
* <li>Display either next previous or current step, or a replacement according to result.</li>
* <li>Proceed with point 2.</li>
* </ol>
*
* @return Overall result of the execution.
* @throws ThreadTerminateException Thrown in case the GUI has been closed externally (interrupted).
*/
public ResultStatus process() throws ThreadTerminateException {
// get first step
StepResult next = navigator.next();
// loop over steps. break inside loop
while (true) {
ResultStatus result = next.getStatus();
// close dialog on cancel and interrupt
if (result == ResultStatus.INTERRUPTED || Thread.currentThread().isInterrupted()) {
navigator.close();
throw new ThreadTerminateException("GUI has been interrupted.");
} else if (result == ResultStatus.CANCEL) {
navigator.close();
return result;
}
// get result and put it in resultmap
List<OutputInfoUnit> stepResults = next.getResults();
Map<String, ExecutionResults> oldResults = Collections.unmodifiableMap(results);
results.put(next.getStepID(), new ExecutionResults(next.getStepID(), stepResults));
// replace InfoInputUnit values in live list
if (!next.getStep().isResetOnLoad()) {
Step s = next.getStep();
List<InputInfoUnit> inputInfo = s.getInputInfoUnits();
Map<String, InputInfoUnit> infoMap = new HashMap<>();
// create index over infos
for (InputInfoUnit nextInfo : inputInfo) {
infoMap.put(nextInfo.getID(), nextInfo);
}
for (OutputInfoUnit nextOut : stepResults) {
InputInfoUnit matchingInfo = infoMap.get(nextOut.getID());
// an entry must exist, otherwise this is an error in the GUI implementation
// this type of error should be found in tests
matchingInfo.copyContentFrom(nextOut);
}
}
// replace step if told by result value
if (next.getReplacement() != null) {
switch(next.getStatus()) {
case BACK:
next = navigator.replacePrevious(next.getReplacement());
break;
case OK:
if (navigator.hasNext()) {
next = navigator.replaceNext(next.getReplacement());
} else {
navigator.close();
return convertStatus(StepActionResultStatus.NEXT);
}
break;
case RELOAD:
next = navigator.replaceCurrent(next.getReplacement());
break;
default:
// fallthrough because CANCEL and INTERRUPTED are already handled
break;
}
} else {
// step replacement did not happen, so we can execute the action
StepAction action = next.getStep().getAction();
StepActionCallable actionCallable = new StepActionCallable(action, oldResults, next);
// use separate thread or tasks running outside the JVM context, like PCSC calls, won't stop on cancellation
ExecutorService execService = Executors.newSingleThreadExecutor();
Future<StepActionResult> actionFuture = execService.submit(actionCallable);
navigator.setRunningAction(actionFuture);
StepActionResult actionResult;
try {
actionResult = actionFuture.get();
} catch (CancellationException ex) {
LOG.info("StepAction was canceled.", ex);
navigator.close();
return ResultStatus.CANCEL;
} catch (InterruptedException ex) {
LOG.info("StepAction was interrupted.", ex);
navigator.close();
throw new ThreadTerminateException("GUI has been interrupted.");
} catch (ExecutionException ex) {
// there are some special kinds we need to handle here
if (ex.getCause() instanceof InvocationTargetExceptionUnchecked) {
InvocationTargetExceptionUnchecked iex = (InvocationTargetExceptionUnchecked) ex.getCause();
if (iex.getCause() instanceof ThreadTerminateException) {
LOG.info("StepAction was interrupted.", ex);
navigator.close();
throw new ThreadTerminateException("GUI has been interrupted.");
}
}
// all other types
LOG.error("StepAction failed with error.", ex.getCause());
navigator.close();
return ResultStatus.CANCEL;
}
// break out if cancel was returned
if (actionResult.getStatus() == StepActionResultStatus.CANCEL) {
LOG.info("StepAction was canceled.");
navigator.close();
return ResultStatus.CANCEL;
}
// replace step if told by result value
if (actionResult.getReplacement() != null) {
switch(actionResult.getStatus()) {
case BACK:
next = navigator.replacePrevious(actionResult.getReplacement());
break;
case NEXT:
if (navigator.hasNext()) {
next = navigator.replaceNext(actionResult.getReplacement());
} else {
navigator.close();
return convertStatus(StepActionResultStatus.NEXT);
}
break;
case REPEAT:
next = navigator.replaceCurrent(actionResult.getReplacement());
break;
default:
// fallthrough because CANCEL is already handled
break;
}
} else {
// no replacement just proceed
switch(actionResult.getStatus()) {
case BACK:
next = navigator.previous();
break;
case NEXT:
if (navigator.hasNext()) {
next = navigator.next();
} else {
navigator.close();
return convertStatus(StepActionResultStatus.NEXT);
}
break;
case REPEAT:
next = navigator.current();
break;
default:
// fallthrough because CANCEL is already handled
break;
}
}
}
}
}
use of org.openecard.common.ThreadTerminateException in project open-ecard by ecsec.
the class ChipGateway method sendHello.
public TerminateType sendHello() throws VersionTooOld, ChipGatewayDataError, ConnectionError, InvalidRedirectUrlException, AuthServerException {
try {
byte[] challenge = ValueGenerators.generateRandom(32);
helloReq = new HelloRequestType();
helloReq.setSessionIdentifier(sessionId);
helloReq.setVersion(String.format("%s.%s.%s", AppVersion.getMajor(), AppVersion.getMinor(), AppVersion.getPatch()));
helloReq.setChallenge(challenge);
// send Hello
String helloReqMsg = mapper.writeValueAsString(helloReq);
HelloResponseType helloResp = sendMessageInterruptable(getResource(helloUrl), helloReqMsg, HelloResponseType.class);
processHelloResponse(helloResp);
// send GetCommand
GetCommandType cmdReq = createGetCommandRequest();
String cmdReqMsg = mapper.writeValueAsString(cmdReq);
CommandType cmdResp;
try {
cmdResp = sendMessageInterruptable(getResource(getCommandUrl), cmdReqMsg, CommandType.class);
} catch (ThreadTerminateException ex) {
performProcessCancelled();
throw ex;
}
// send messages to the server as long as there is no termination response
while (cmdResp.getTerminate() == null) {
ListTokensRequestType tokensReq = cmdResp.getListTokensRequest();
ListCertificatesRequestType certReq = cmdResp.getListCertificatesRequest();
SignRequestType signReq = cmdResp.getSignRequest();
if (tokensReq != null) {
cmdResp = processTokensRequest(tokensReq);
} else if (certReq != null) {
cmdResp = processCertificatesRequest(certReq);
} else if (signReq != null) {
cmdResp = processSignRequest(signReq);
} else {
throw new ChipGatewayDataError(token.finalizeErrorAddress(ResultMinor.SERVER_ERROR), INVALID_CHIPGATEWAY_MSG);
}
}
// return the last message (terminate type)
return cmdResp.getTerminate();
} catch (JsonProcessingException ex) {
throw new ChipGatewayDataError(token.finalizeErrorAddress(ResultMinor.CLIENT_ERROR), INVALID_CHIPGATEWAY_MSG, ex);
} finally {
// clear token cache and delete all pins in it
tokenCache.clearPins();
// display GUI if needed
if (showDialogThread != null) {
showDialogThread.start();
}
try {
// in case we are interrupted, terminate is sent in the background, so don't close just yet
if (conn != null && !isInterrupted) {
conn.close();
}
} catch (IOException ex) {
LOG.error("Failed to close connection to server.", ex);
}
// disconnect all slots which have been connected in the process
for (byte[] nextSlot : connectedSlots) {
if (LOG.isDebugEnabled()) {
LOG.debug("Disconnecting card with slotHandle={}.", ByteUtils.toHexString(nextSlot));
}
CardApplicationDisconnect req = new CardApplicationDisconnect();
// req.setAction(ActionType.RESET);
ConnectionHandleType handle = HandlerBuilder.create().setSlotHandle(nextSlot).buildConnectionHandle();
req.setConnectionHandle(handle);
dispatcher.safeDeliver(req);
}
}
}
Aggregations