Search in sources :

Example 1 with SCIOException

use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.

the class IfdEventRunner method fireEvents.

private void fireEvents(@Nonnull List<IFDStatusType> diff) {
    for (IFDStatusType term : diff) {
        String ifdName = term.getIFDName();
        // find out if the terminal is new, or only a slot got updated
        IFDStatusType oldTerm = getCorresponding(ifdName, currentState);
        boolean terminalAdded = oldTerm == null;
        IFDCapabilitiesType slotCapabilities = getCapabilities(ifdName);
        if (terminalAdded) {
            // TERMINAL ADDED
            // make copy of term
            oldTerm = new IFDStatusType();
            oldTerm.setIFDName(ifdName);
            oldTerm.setConnected(true);
            // add to current list
            currentState.add(oldTerm);
            // create event
            ConnectionHandleType h = makeConnectionHandle(ifdName, null, slotCapabilities);
            LOG.debug("Found a terminal added event ({}).", ifdName);
            env.getEventDispatcher().notify(EventType.TERMINAL_ADDED, new IfdEventObject(h));
        }
        // check each slot
        for (SlotStatusType slot : term.getSlotStatus()) {
            SlotStatusType oldSlot = getCorresponding(slot.getIndex(), oldTerm.getSlotStatus());
            boolean cardPresent = slot.isCardAvailable();
            boolean cardWasPresent = oldSlot != null && oldSlot.isCardAvailable();
            if (cardPresent && !cardWasPresent) {
                // CARD INSERTED
                // copy slot and add to list
                SlotStatusType newSlot = oldSlot;
                if (newSlot == null) {
                    newSlot = new SlotStatusType();
                    oldTerm.getSlotStatus().add(newSlot);
                }
                newSlot.setIndex(slot.getIndex());
                newSlot.setCardAvailable(true);
                newSlot.setATRorATS(slot.getATRorATS());
                // create event
                LOG.debug("Found a card insert event ({}).", ifdName);
                LOG.info("Card with ATR={} inserted.", ByteUtils.toHexString(slot.getATRorATS()));
                ConnectionHandleType handle = makeUnknownCardHandle(ifdName, newSlot, slotCapabilities);
                env.getEventDispatcher().notify(EventType.CARD_INSERTED, new IfdEventObject(handle));
                try {
                    SingleThreadChannel ch = cm.openMasterChannel(ifdName);
                    if (evtManager.isRecognize()) {
                        String proto = ch.getChannel().getCard().getProtocol().toUri();
                        evtManager.threadPool.submit(new Recognizer(env, handle, proto));
                    }
                } catch (NoSuchTerminal | SCIOException ex) {
                    LOG.error("Failed to connect card, nevertheless sending CARD_INSERTED event.", ex);
                }
            } else if (!terminalAdded && !cardPresent && cardWasPresent) {
                // this makes only sense when the terminal was already there
                // CARD REMOVED
                // remove slot entry
                BigInteger idx = oldSlot.getIndex();
                Iterator<SlotStatusType> it = oldTerm.getSlotStatus().iterator();
                while (it.hasNext()) {
                    SlotStatusType next = it.next();
                    if (idx.equals(next.getIndex())) {
                        it.remove();
                        break;
                    }
                }
                LOG.debug("Found a card removed event ({}).", ifdName);
                ConnectionHandleType h = makeConnectionHandle(ifdName, idx, slotCapabilities);
                env.getEventDispatcher().notify(EventType.CARD_REMOVED, new IfdEventObject(h));
            }
        }
        // terminal removed event comes after card removed events
        boolean terminalPresent = term.isConnected();
        if (!terminalPresent) {
            // TERMINAL REMOVED
            Iterator<IFDStatusType> it = currentState.iterator();
            while (it.hasNext()) {
                IFDStatusType toDel = it.next();
                if (toDel.getIFDName().equals(term.getIFDName())) {
                    it.remove();
                }
            }
            ConnectionHandleType h = makeConnectionHandle(ifdName, null, slotCapabilities);
            LOG.debug("Found a terminal removed event ({}).", ifdName);
            env.getEventDispatcher().notify(EventType.TERMINAL_REMOVED, new IfdEventObject(h));
        }
    }
}
Also used : ConnectionHandleType(iso.std.iso_iec._24727.tech.schema.ConnectionHandleType) NoSuchTerminal(org.openecard.common.ifd.scio.NoSuchTerminal) SingleThreadChannel(org.openecard.ifd.scio.wrapper.SingleThreadChannel) SCIOException(org.openecard.common.ifd.scio.SCIOException) IFDCapabilitiesType(iso.std.iso_iec._24727.tech.schema.IFDCapabilitiesType) Iterator(java.util.Iterator) BigInteger(java.math.BigInteger) IFDStatusType(iso.std.iso_iec._24727.tech.schema.IFDStatusType) SlotStatusType(iso.std.iso_iec._24727.tech.schema.SlotStatusType) IfdEventObject(org.openecard.common.event.IfdEventObject)

Example 2 with SCIOException

use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.

the class IFD method beginTransaction.

@Override
public BeginTransactionResponse beginTransaction(BeginTransaction beginTransaction) {
    try {
        BeginTransactionResponse response;
        if (!hasContext()) {
            String msg = "Context not initialized.";
            Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
            response = WSHelper.makeResponse(BeginTransactionResponse.class, r);
            return response;
        }
        try {
            byte[] handle = beginTransaction.getSlotHandle();
            SingleThreadChannel ch = cm.getSlaveChannel(handle);
            ch.beginExclusive();
        } catch (NoSuchChannel | IllegalStateException ex) {
            String msg = "No card available in the requested terminal.";
            Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
            response = WSHelper.makeResponse(BeginTransactionResponse.class, r);
            LOG.warn(msg, ex);
            return response;
        } catch (SCIOException ex) {
            String msg;
            String minor;
            switch(ex.getCode()) {
                case SCARD_W_RESET_CARD:
                case SCARD_W_REMOVED_CARD:
                case SCARD_E_READER_UNAVAILABLE:
                case SCARD_E_NO_SMARTCARD:
                case SCARD_E_NO_SERVICE:
                    msg = String.format("Slot handle is not available [%s].", ex.getCode().name());
                    minor = ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE;
                    LOG.debug(msg, ex);
                    break;
                default:
                    msg = "Unknown error in the underlying SCIO implementation.";
                    minor = ECardConstants.Minor.App.UNKNOWN_ERROR;
                    LOG.warn(msg, ex);
            }
            Result r = WSHelper.makeResultError(minor, msg);
            response = WSHelper.makeResponse(BeginTransactionResponse.class, r);
            return response;
        }
        response = WSHelper.makeResponse(BeginTransactionResponse.class, WSHelper.makeResultOK());
        return response;
    } catch (Exception ex) {
        LOG.warn(ex.getMessage(), ex);
        throwThreadKillException(ex);
        return WSHelper.makeResponse(BeginTransactionResponse.class, WSHelper.makeResult(ex));
    }
}
Also used : SingleThreadChannel(org.openecard.ifd.scio.wrapper.SingleThreadChannel) NoSuchChannel(org.openecard.ifd.scio.wrapper.NoSuchChannel) SCIOException(org.openecard.common.ifd.scio.SCIOException) ThreadTerminateException(org.openecard.common.ThreadTerminateException) SCIOException(org.openecard.common.ifd.scio.SCIOException) ExecutionException(java.util.concurrent.ExecutionException) BeginTransactionResponse(iso.std.iso_iec._24727.tech.schema.BeginTransactionResponse) Result(oasis.names.tc.dss._1_0.core.schema.Result)

Example 3 with SCIOException

use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.

the class IFD method transmit.

@Publish
@Override
public TransmitResponse transmit(Transmit parameters) {
    try {
        TransmitResponse response;
        if (!hasContext()) {
            String msg = "Context not initialized.";
            Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
            response = WSHelper.makeResponse(TransmitResponse.class, r);
            return response;
        }
        try {
            byte[] handle = parameters.getSlotHandle();
            SingleThreadChannel ch = cm.getSlaveChannel(handle);
            List<InputAPDUInfoType> apdus = parameters.getInputAPDUInfo();
            // check that the apdus contain sane values
            for (InputAPDUInfoType apdu : apdus) {
                for (byte[] code : apdu.getAcceptableStatusCode()) {
                    if (code.length == 0 || code.length > 2) {
                        String msg = "Invalid accepted status code given.";
                        Result r = WSHelper.makeResultError(ECardConstants.Minor.App.PARM_ERROR, msg);
                        response = WSHelper.makeResponse(TransmitResponse.class, r);
                        return response;
                    }
                }
            }
            // transmit APDUs and stop if an error occurs or a not expected status is hit
            response = WSHelper.makeResponse(TransmitResponse.class, WSHelper.makeResultOK());
            Result result;
            List<byte[]> rapdus = response.getOutputAPDU();
            try {
                for (InputAPDUInfoType capdu : apdus) {
                    byte[] rapdu = ch.transmit(capdu.getInputAPDU(), capdu.getAcceptableStatusCode());
                    rapdus.add(rapdu);
                }
                result = WSHelper.makeResultOK();
            } catch (TransmitException ex) {
                rapdus.add(ex.getResponseAPDU());
                result = ex.getResult();
            } catch (SCIOException ex) {
                String msg = "Error during transmit.";
                LOG.warn(msg, ex);
                result = WSHelper.makeResultUnknownError(msg);
            } catch (IllegalStateException ex) {
                String msg = "Card removed during transmit.";
                LOG.warn(msg, ex);
                result = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
            } catch (IllegalArgumentException ex) {
                String msg = "Given command contains a MANAGE CHANNEL APDU.";
                LOG.error(msg, ex);
                result = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
            }
            response.setResult(result);
            return response;
        } catch (NoSuchChannel | IllegalStateException ex) {
            String msg = "No card with transaction available in the requested terminal.";
            Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
            response = WSHelper.makeResponse(TransmitResponse.class, r);
            LOG.warn(msg, ex);
            return response;
        }
    } catch (Exception ex) {
        LOG.warn(ex.getMessage(), ex);
        throwThreadKillException(ex);
        return WSHelper.makeResponse(TransmitResponse.class, WSHelper.makeResult(ex));
    }
}
Also used : SingleThreadChannel(org.openecard.ifd.scio.wrapper.SingleThreadChannel) SCIOException(org.openecard.common.ifd.scio.SCIOException) NoSuchChannel(org.openecard.ifd.scio.wrapper.NoSuchChannel) InputAPDUInfoType(iso.std.iso_iec._24727.tech.schema.InputAPDUInfoType) ThreadTerminateException(org.openecard.common.ThreadTerminateException) SCIOException(org.openecard.common.ifd.scio.SCIOException) ExecutionException(java.util.concurrent.ExecutionException) Result(oasis.names.tc.dss._1_0.core.schema.Result) TransmitResponse(iso.std.iso_iec._24727.tech.schema.TransmitResponse) Publish(org.openecard.common.interfaces.Publish)

Example 4 with SCIOException

use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.

the class IFD method getIFDCapabilities.

@Override
public GetIFDCapabilitiesResponse getIFDCapabilities(GetIFDCapabilities parameters) {
    GetIFDCapabilitiesResponse response;
    // you thought of a different IFD obviously
    if (!ByteUtils.compare(ctxHandle, parameters.getContextHandle())) {
        String msg = "Invalid context handle specified.";
        Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_CONTEXT_HANDLE, msg);
        response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, r);
        return response;
    }
    try {
        TerminalInfo info;
        String ifdName = parameters.getIFDName();
        try {
            SingleThreadChannel channel = cm.openMasterChannel(ifdName);
            info = new TerminalInfo(cm, channel);
        } catch (NoSuchTerminal ex) {
            // continue without a channel
            SCIOTerminal term = cm.getTerminals().getTerminal(ifdName);
            info = new TerminalInfo(cm, term);
        }
        IFDCapabilitiesType cap = new IFDCapabilitiesType();
        // slot capability
        SlotCapabilityType slotCap = info.getSlotCapability();
        cap.getSlotCapability().add(slotCap);
        // ask protocol factory which types it supports
        List<String> protocols = slotCap.getProtocol();
        for (String proto : protocolFactories.protocols()) {
            if (!protocols.contains(proto)) {
                protocols.add(proto);
            }
        }
        // TODO: PIN Compare should be a part of establishChannel and thus just appear in the software protocol list
        if (!protocols.contains(ECardConstants.Protocol.PIN_COMPARE)) {
            protocols.add(ECardConstants.Protocol.PIN_COMPARE);
        }
        // display capability
        DisplayCapabilityType dispCap = info.getDisplayCapability();
        if (dispCap != null) {
            cap.getDisplayCapability().add(dispCap);
        }
        // keypad capability
        KeyPadCapabilityType keyCap = info.getKeypadCapability();
        if (keyCap != null) {
            cap.getKeyPadCapability().add(keyCap);
        }
        // biosensor capability
        BioSensorCapabilityType bioCap = info.getBiosensorCapability();
        if (bioCap != null) {
            cap.getBioSensorCapability().add(bioCap);
        }
        // acoustic and optical elements
        cap.setOpticalSignalUnit(info.isOpticalSignal());
        cap.setAcousticSignalUnit(info.isAcousticSignal());
        // prepare response
        response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, WSHelper.makeResultOK());
        response.setIFDCapabilities(cap);
        return response;
    } catch (NullPointerException | NoSuchTerminal ex) {
        String msg = String.format("Requested terminal not found.");
        LOG.warn(msg, ex);
        Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.Terminal.UNKNOWN_IFD, msg);
        response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, r);
        return response;
    } catch (SCIOException ex) {
        String msg = String.format("Failed to request status from terminal.");
        // use debug when card has been removed, as this happens all the time
        SCIOErrorCode code = ex.getCode();
        if (!(code == SCIOErrorCode.SCARD_E_NO_SMARTCARD || code == SCIOErrorCode.SCARD_W_REMOVED_CARD)) {
            LOG.warn(msg, ex);
        } else {
            LOG.debug(msg, ex);
        }
        Result r = WSHelper.makeResultUnknownError(msg);
        response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, r);
        return response;
    }
}
Also used : SlotCapabilityType(iso.std.iso_iec._24727.tech.schema.SlotCapabilityType) NoSuchTerminal(org.openecard.common.ifd.scio.NoSuchTerminal) SingleThreadChannel(org.openecard.ifd.scio.wrapper.SingleThreadChannel) SCIOException(org.openecard.common.ifd.scio.SCIOException) SCIOTerminal(org.openecard.common.ifd.scio.SCIOTerminal) DisplayCapabilityType(iso.std.iso_iec._24727.tech.schema.DisplayCapabilityType) IFDCapabilitiesType(iso.std.iso_iec._24727.tech.schema.IFDCapabilitiesType) TerminalInfo(org.openecard.ifd.scio.wrapper.TerminalInfo) Result(oasis.names.tc.dss._1_0.core.schema.Result) KeyPadCapabilityType(iso.std.iso_iec._24727.tech.schema.KeyPadCapabilityType) SCIOErrorCode(org.openecard.common.ifd.scio.SCIOErrorCode) GetIFDCapabilitiesResponse(iso.std.iso_iec._24727.tech.schema.GetIFDCapabilitiesResponse) BioSensorCapabilityType(iso.std.iso_iec._24727.tech.schema.BioSensorCapabilityType)

Example 5 with SCIOException

use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.

the class IFD method wait.

@Override
public WaitResponse wait(Wait parameters) {
    WaitResponse response;
    // you thought of a different IFD obviously
    if (!ByteUtils.compare(ctxHandle, parameters.getContextHandle())) {
        String msg = "Invalid context handle specified.";
        Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_CONTEXT_HANDLE, msg);
        response = WSHelper.makeResponse(WaitResponse.class, r);
        return response;
    }
    // get timeout value
    BigInteger timeout = parameters.getTimeOut();
    if (timeout == null) {
        timeout = BigInteger.valueOf(Long.MAX_VALUE);
    }
    if (timeout.signum() == -1 || timeout.signum() == 0) {
        String msg = "Invalid timeout value given, must be strictly positive.";
        Result r = WSHelper.makeResultUnknownError(msg);
        response = WSHelper.makeResponse(WaitResponse.class, r);
        return response;
    }
    long timeoutL;
    try {
        timeoutL = (long) timeout.doubleValue();
    } catch (ArithmeticException ex) {
        LOG.warn("Too big timeout value give, shortening to Long.MAX_VALUE.");
        timeoutL = Long.MAX_VALUE;
    }
    ChannelHandleType callback = parameters.getCallback();
    // callback is only useful with a protocol termination point
    if (callback != null && callback.getProtocolTerminationPoint() == null) {
        callback = null;
    }
    // if callback, generate session id
    String sessionId = null;
    if (callback != null) {
        ChannelHandleType newCallback = new ChannelHandleType();
        newCallback.setBinding(callback.getBinding());
        newCallback.setPathSecurity(callback.getPathSecurity());
        newCallback.setProtocolTerminationPoint(callback.getProtocolTerminationPoint());
        sessionId = ValueGenerators.genBase64Session();
        newCallback.setSessionIdentifier(sessionId);
        callback = newCallback;
    }
    try {
        EventWatcher watcher = new EventWatcher(cm, timeoutL, callback);
        List<IFDStatusType> initialState = watcher.start();
        // get expected status or initial status for all if none specified
        List<IFDStatusType> expectedState = parameters.getIFDStatus();
        if (expectedState.isEmpty()) {
            expectedState = initialState;
        } else {
            for (IFDStatusType s : expectedState) {
                // check that ifdname is present, needed for comparison
                if (s.getIFDName() == null) {
                    String msg = "IFD in a request IFDStatus not known.";
                    Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.Terminal.UNKNOWN_IFD, msg);
                    response = WSHelper.makeResponse(WaitResponse.class, r);
                    return response;
                }
                // check that at least one slot entry is present
                if (s.getSlotStatus().isEmpty()) {
                    // assume an empty one
                    SlotStatusType slot = new SlotStatusType();
                    slot.setCardAvailable(false);
                    slot.setIndex(BigInteger.ZERO);
                    s.getSlotStatus().add(slot);
                }
            }
        }
        watcher.setExpectedState(expectedState);
        // create the future and fire
        FutureTask<List<IFDStatusType>> future = new FutureTask<>(watcher);
        if (watcher.isAsync()) {
            // add future to async wait list
            asyncWaitThreads.put(sessionId, future);
            // finally run this darn thingy
            threadPool.execute(future);
            // prepare result with session id in it
            response = WSHelper.makeResponse(WaitResponse.class, WSHelper.makeResultOK());
            response.setSessionIdentifier(sessionId);
            return response;
        } else {
            // run wait in a future so it can be easily interrupted
            syncWaitThread = future;
            threadPool.execute(future);
            // get results from the future
            List<IFDStatusType> events = future.get();
            // prepare response
            response = WSHelper.makeResponse(WaitResponse.class, WSHelper.makeResultOK());
            response.getIFDEvent().addAll(events);
            return response;
        }
    } catch (SCIOException ex) {
        String msg = "Unknown SCIO error occured during wait call.";
        LOG.warn(msg, ex);
        Result r = WSHelper.makeResultUnknownError(msg);
        response = WSHelper.makeResponse(WaitResponse.class, r);
        return response;
    } catch (ExecutionException ex) {
        // this is the exception from within the future
        Throwable cause = ex.getCause();
        if (cause instanceof SCIOException) {
            String msg = "Unknown SCIO error occured during wait call.";
            LOG.warn(msg, cause);
            Result r = WSHelper.makeResultUnknownError(msg);
            response = WSHelper.makeResponse(WaitResponse.class, r);
        } else {
            String msg = "Unknown error during wait call.";
            LOG.error(msg, cause);
            Result r = WSHelper.makeResultUnknownError(msg);
            response = WSHelper.makeResponse(WaitResponse.class, r);
        }
        return response;
    } catch (InterruptedException ex) {
        String msg = "Wait interrupted by another thread.";
        LOG.warn(msg, ex);
        Result r = WSHelper.makeResultUnknownError(msg);
        response = WSHelper.makeResponse(WaitResponse.class, r);
        return response;
    }
}
Also used : SCIOException(org.openecard.common.ifd.scio.SCIOException) ChannelHandleType(iso.std.iso_iec._24727.tech.schema.ChannelHandleType) WaitResponse(iso.std.iso_iec._24727.tech.schema.WaitResponse) Result(oasis.names.tc.dss._1_0.core.schema.Result) FutureTask(java.util.concurrent.FutureTask) BigInteger(java.math.BigInteger) IFDStatusType(iso.std.iso_iec._24727.tech.schema.IFDStatusType) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) SlotStatusType(iso.std.iso_iec._24727.tech.schema.SlotStatusType) ExecutionException(java.util.concurrent.ExecutionException)

Aggregations

SCIOException (org.openecard.common.ifd.scio.SCIOException)19 Result (oasis.names.tc.dss._1_0.core.schema.Result)10 SingleThreadChannel (org.openecard.ifd.scio.wrapper.SingleThreadChannel)10 NoSuchTerminal (org.openecard.common.ifd.scio.NoSuchTerminal)7 ExecutionException (java.util.concurrent.ExecutionException)6 IFDStatusType (iso.std.iso_iec._24727.tech.schema.IFDStatusType)5 ThreadTerminateException (org.openecard.common.ThreadTerminateException)5 NoSuchChannel (org.openecard.ifd.scio.wrapper.NoSuchChannel)5 SlotStatusType (iso.std.iso_iec._24727.tech.schema.SlotStatusType)4 SCIOTerminal (org.openecard.common.ifd.scio.SCIOTerminal)4 BigInteger (java.math.BigInteger)3 ArrayList (java.util.ArrayList)3 LinkedList (java.util.LinkedList)3 BeginTransactionResponse (iso.std.iso_iec._24727.tech.schema.BeginTransactionResponse)2 ConnectionHandleType (iso.std.iso_iec._24727.tech.schema.ConnectionHandleType)2 IFDCapabilitiesType (iso.std.iso_iec._24727.tech.schema.IFDCapabilitiesType)2 CardException (javax.smartcardio.CardException)2 SCIOErrorCode (org.openecard.common.ifd.scio.SCIOErrorCode)2 TerminalInfo (org.openecard.ifd.scio.wrapper.TerminalInfo)2 IsoDep (android.nfc.tech.IsoDep)1