From 32d17447a258188b2d534bcb0bf65a659ba7b7d0 Mon Sep 17 00:00:00 2001 From: mcentner Date: Fri, 29 Aug 2008 12:11:34 +0000 Subject: Initial import. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@1 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smccSTAL/src/main/java/META-INF/MANIFEST.MF | 3 + .../egiz/bku/smccstal/AbstractRequestHandler.java | 86 ++++++++++++ .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 116 ++++++++++++++++ .../at/gv/egiz/bku/smccstal/DomainIdConverter.java | 85 ++++++++++++ .../bku/smccstal/InfoBoxReadRequestHandler.java | 140 +++++++++++++++++++ .../egiz/bku/smccstal/SMCCSTALRequestHandler.java | 36 +++++ .../gv/egiz/bku/smccstal/STALMessageConsumer.java | 21 +++ .../gv/egiz/bku/smccstal/SignRequestHandler.java | 151 +++++++++++++++++++++ .../src/test/java/at/gv/egiz/smcc/ASN1Test.java | 105 ++++++++++++++ 9 files changed, 743 insertions(+) create mode 100644 smccSTAL/src/main/java/META-INF/MANIFEST.MF create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java create mode 100644 smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java (limited to 'smccSTAL/src') diff --git a/smccSTAL/src/main/java/META-INF/MANIFEST.MF b/smccSTAL/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 00000000..5e949512 --- /dev/null +++ b/smccSTAL/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java new file mode 100644 index 00000000..e5afa478 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java @@ -0,0 +1,86 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.smccstal; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +public abstract class AbstractRequestHandler implements SMCCSTALRequestHandler, + ActionListener { + private final static Log log = LogFactory + .getLog(AbstractRequestHandler.class); + + protected SignatureCard card; + protected BKUGUIFacade gui; + protected static STALMessageConsumer messageConsumer = null; + protected String actionCommand; + protected boolean actionPerformed = false; + + @Override + public abstract STALResponse handleRequest(STALRequest request); + + @Override + public void init(SignatureCard sc, BKUGUIFacade gui) { + if ((sc == null) || (gui == null)) { + throw new NullPointerException("Parameter must not be set to null"); + } + this.card = sc; + this.gui = gui; + } + + public static void setMessageConsumer(STALMessageConsumer messageConsumer) { + AbstractRequestHandler.messageConsumer = messageConsumer; + } + + protected static void newSTALMessage(String caption, String message) { + if (messageConsumer != null) { + messageConsumer.consumeNewSTALMessage(caption, message); + } + } + + protected synchronized void waitForAction() { + try { + while (!actionPerformed) { + wait(); + } + } catch (InterruptedException e) { + log.info(e); + } + actionPerformed = false; + } + + private synchronized void actionPerformed() { + actionPerformed = true; + notifyAll(); + } + + @Override + public void actionPerformed(ActionEvent e) { + actionCommand = e.getActionCommand(); + actionPerformed(); + } + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java new file mode 100644 index 00000000..7bd9e264 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -0,0 +1,116 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.smccstal; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.util.SMCCHelper; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; + +public abstract class AbstractSMCCSTAL implements STAL { + private static Log log = LogFactory.getLog(AbstractSMCCSTAL.class); + + protected Locale locale = Locale.getDefault(); + protected SMCCHelper smccHelper = new SMCCHelper(); + protected SignatureCard signatureCard = null; + protected static Map handlerMap = new HashMap(); + + static { + addRequestHandler(InfoboxReadRequest.class, new InfoBoxReadRequestHandler()); + addRequestHandler(SignRequest.class, new SignRequestHandler()); + } + + public AbstractSMCCSTAL() { + } + + /** + * Implementations must assign the signature card within this method. + * + * @return if the user canceled + */ + protected abstract boolean waitForCard(); + + protected abstract BKUGUIFacade getGUI(); + + @Override + public List handleRequest( + List requestList) { + log.debug("Got request list containing " + requestList.size() + + " STAL requests"); + List responseList = new ArrayList(requestList + .size()); + for (STALRequest request : requestList) { + log.info("Processing: " + request); + SMCCSTALRequestHandler handler = null; + handler = handlerMap.get(request.getClass().getSimpleName()); + if (handler != null) { + if (handler.requireCard()) { + if (waitForCard()) { + responseList.add(new ErrorResponse(6001)); + break; + } + } + try { + handler = handler.newInstance(); + handler.init(signatureCard, getGUI()); + responseList.add(handler.handleRequest(request)); + } catch (Exception e) { + log.info("Error while handling STAL request:" + e); + responseList.add(new ErrorResponse(6000)); + } + } else { + log.error("Cannot find a handler for STAL request: " + request); + responseList.add(new ErrorResponse()); + } + } + return responseList; + } + + public static void addRequestHandler(Class id, + SMCCSTALRequestHandler handler) { + log.debug("Registering STAL request handler: " + id.getSimpleName()); + handlerMap.put(id.getSimpleName(), handler); + } + + public static SMCCSTALRequestHandler getRequestHandler( + Class request) { + return handlerMap.get(request.getSimpleName()); + } + + @Override + public void setLocale(Locale locale) { + if (locale == null) { + throw new NullPointerException("Locale must not be set to null"); + } + this.locale = locale; + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java new file mode 100644 index 00000000..3a564b91 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java @@ -0,0 +1,85 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.smccstal; + +import iaik.me.asn1.ASN1; +import iaik.me.utils.Base64; + +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Vector; + +public class DomainIdConverter { + + private static String getBaseId(ASN1 identityLink) throws IOException { + + if (identityLink.getType() == ASN1.TYPE_SEQUENCE) { + ASN1 personData = identityLink.getElementAt(4); + if (personData.getType() == ASN1.TAG_CONTEXT_SPECIFIC) { + ASN1 physicalPersonData = personData.gvASN1(); + ASN1 baseId = physicalPersonData.getElementAt(0); + return baseId.gvString(); + } + throw new IOException("Invalid structure."); + + } + throw new IOException("Invalid structure."); + + } + + private static ASN1 replaceBaseId(ASN1 identityLink, String newBaseId) + throws IOException { + + ASN1 newIdentityLink = new ASN1(ASN1.TYPE_SEQUENCE, new Vector()); + for (int i = 0; i < identityLink.getSize(); i++) { + ASN1 asn1 = identityLink.getElementAt(i); + if (i == 4 && asn1.getType() == ASN1.TAG_CONTEXT_SPECIFIC) { + ASN1 physicalPersonData = asn1.gvASN1(); + ASN1 newPhysicalPersonData = new ASN1(ASN1.TYPE_SEQUENCE, + new Vector()); + newPhysicalPersonData.addElement(new ASN1(ASN1.TYPE_UTF8_STRING, + newBaseId)); + for (int j = 1; j < physicalPersonData.getSize(); j++) { + newPhysicalPersonData.addElement(physicalPersonData.getElementAt(j)); + } + asn1 = new ASN1(ASN1.TAG_CONTEXT_SPECIFIC, newPhysicalPersonData); + } + newIdentityLink.addElement(asn1); + } + return newIdentityLink; + + } + + public static byte[] convertDomainId(byte[] data, String domainId) + throws IOException, NoSuchAlgorithmException { + if (domainId == null) { + return data; + } + ASN1 identityLink = new ASN1(data); + MessageDigest sha = null; + sha = MessageDigest.getInstance("SHA"); + String base = getBaseId(identityLink); + sha.update((base + "+" + domainId).getBytes()); + String bpkStr = new String(Base64.encode(sha.digest())); + bpkStr = bpkStr.trim(); + identityLink = replaceBaseId(identityLink, bpkStr); + System.out.println(getBaseId(identityLink)); + return identityLink.getEncoded(); + } + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java new file mode 100644 index 00000000..7dc2e202 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java @@ -0,0 +1,140 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.smccstal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.InfoboxReadResponse; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements + PINProvider { + + private static Log log = LogFactory.getLog(InfoBoxReadRequestHandler.class); + + private int retryCounter = 0; + + @Override + public STALResponse handleRequest(STALRequest request) { + if (request instanceof InfoboxReadRequest) { + InfoboxReadRequest infoBox = (InfoboxReadRequest) request; + try { + if (infoBox.getInfoboxIdentifier().equals("IdentityLink")) { + newSTALMessage("Message.RequestCaption", "Message.IdentityLink"); + log.debug("Handling identitylink infobox"); + byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this, + infoBox.getDomainIdentifier()); + if (resp == null) { + log.info("Got null as result->user cancelled"); + return new ErrorResponse(6001); + } else { + try { + resp = DomainIdConverter.convertDomainId(resp, infoBox + .getDomainIdentifier()); + } catch (Exception e) { + log.error("Cannot convert domain specific id", e); + return new ErrorResponse(1000); + } + } + InfoboxReadResponse stalResp = new InfoboxReadResponse(); + stalResp.setInfoboxValue(resp); + return stalResp; + } else if (SignatureCard.KeyboxName.CERITIFIED_KEYPAIR.equals(infoBox + .getInfoboxIdentifier())) { + newSTALMessage("Message.RequestCaption", "Message.CertifiedKeypair"); + log.debug("Handling certified keypair infobox"); + byte[] resp = card + .getCertificate(SignatureCard.KeyboxName.CERITIFIED_KEYPAIR); + if (resp == null) { + return new ErrorResponse(6001); + } + InfoboxReadResponse stalResp = new InfoboxReadResponse(); + stalResp.setInfoboxValue(resp); + return stalResp; + } else if (SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR + .equals(infoBox.getInfoboxIdentifier())) { + newSTALMessage("Message.RequestCaption", + "Message.SecureSignatureKeypair"); + log.debug("Handling secure signature keypair infobox"); + byte[] resp = card + .getCertificate(SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR); + if (resp == null) { + return new ErrorResponse(6001); + } + InfoboxReadResponse stalResp = new InfoboxReadResponse(); + stalResp.setInfoboxValue(resp); + return stalResp; + } else { + newSTALMessage("Message.RequestCaption", "Message.InfoboxReadRequest"); + log.warn("Unknown infobox identifier: " + + infoBox.getInfoboxIdentifier() + " trying generic request"); + byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this, + infoBox.getDomainIdentifier()); + if (resp == null) { + return new ErrorResponse(6001); + } + InfoboxReadResponse stalResp = new InfoboxReadResponse(); + stalResp.setInfoboxValue(resp); + return stalResp; + } + } catch (CancelledException cx) { + log.debug("User cancelled request", cx); + return new ErrorResponse(6001); + } catch (SignatureCardException e) { + log.info("Error while reading infobox: " + e); + return new ErrorResponse(4000); + } + } else { + log.fatal("Got unexpected STAL request: " + request); + return new ErrorResponse(1000); + } + } + + @Override + public boolean requireCard() { + return true; + } + + @Override + public String providePIN(PINSpec spec, int retries) { + if (retryCounter++ > 0) { + log.info("PIN wrong retrying ..."); + gui.showCardPINRetryDialog(spec, retries, this, "ok", this, "cancel"); + } else { + gui.showCardPINDialog(spec, this, "ok", this, "cancel"); + } + waitForAction(); + if (actionCommand.equals("cancel")) { + return null; + } + return new String(gui.getPin()); + } + + @Override + public SMCCSTALRequestHandler newInstance() { + return new InfoBoxReadRequestHandler(); + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java new file mode 100644 index 00000000..7badb2a0 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java @@ -0,0 +1,36 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.smccstal; + + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +public interface SMCCSTALRequestHandler { + + public void init(SignatureCard sc, BKUGUIFacade gui); + + public STALResponse handleRequest(STALRequest request); + + public boolean requireCard(); + + public SMCCSTALRequestHandler newInstance(); + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java new file mode 100644 index 00000000..7d7a6ec0 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java @@ -0,0 +1,21 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.smccstal; + +public interface STALMessageConsumer { + public void consumeNewSTALMessage(String captionId, String messageId); +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java new file mode 100644 index 00000000..6ae4fa01 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -0,0 +1,151 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.smccstal; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.SignatureCard.KeyboxName; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.SignResponse; +import at.gv.egiz.stal.signedinfo.ObjectFactory; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import at.gv.egiz.stal.util.JCEAlgorithmNames; + +public class SignRequestHandler extends AbstractRequestHandler implements + PINProvider { + private static Log log = LogFactory.getLog(SignRequestHandler.class); + + private static JAXBContext jaxbContext; + + static { + try { + jaxbContext = JAXBContext.newInstance(ObjectFactory.class.getPackage() + .getName()); + } catch (JAXBException e) { + log.fatal("Cannot init jaxbContext", e); + } + } + + private int retryCounter = 0; + + public SignRequestHandler() { + } + + @SuppressWarnings("unchecked") + @Override + public STALResponse handleRequest(STALRequest request) { + if (request instanceof SignRequest) { + SignRequest signReq = (SignRequest) request; + newSTALMessage("Message.RequestCaption", "Message.SignRequest"); + try { + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + InputStream is = new ByteArrayInputStream(signReq.getSignedInfo()); + JAXBElement signedInfo = (JAXBElement) unmarshaller + .unmarshal(is); + String signatureMethod = signedInfo.getValue().getSignatureMethod() + .getAlgorithm(); + log.debug("Found signature method: " + signatureMethod); + String jceName = JCEAlgorithmNames.getJCEHashName(signatureMethod); + if (jceName == null) { + log.error("Hash algorithm not supported:"); + return new ErrorResponse(1000); + } + MessageDigest md = MessageDigest.getInstance(jceName); + md.update(signReq.getSignedInfo()); + KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq + .getKeyIdentifier()); + byte[] resp = card.createSignature(md.digest(), kb, this); + if (resp == null) { + return new ErrorResponse(6001); + } + SignResponse stalResp = new SignResponse(); + stalResp.setSignatureValue(resp); + return stalResp; + } catch (CancelledException cx) { + log.debug("User cancelled request"); + return new ErrorResponse(6001); + } catch (SignatureCardException e) { + log.error("Error while creating signature: " + e); + return new ErrorResponse(4000); + } catch (JAXBException e) { + log.error("Cannot unmarshall signed info", e); + return new ErrorResponse(1000); + } catch (NoSuchAlgorithmException e) { + log.error(e); + return new ErrorResponse(1000); + } + } else { + log.fatal("Got unexpected STAL request: " + request); + return new ErrorResponse(1000); + } + } + + @Override + public boolean requireCard() { + return true; + } + + @Override + public String providePIN(PINSpec spec, int retries) { + if (retryCounter++ > 0) { + log.info("PIN wrong retrying ..."); + gui.showSignaturePINRetryDialog(spec, retries, this, "sign", this, + "cancel", this, "hashData"); + } else { + gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, + "hashData"); + } + do { + waitForAction(); + if (actionCommand.equals("cancel")) { + return null; + } else if (actionCommand.equals("hashData")) { + // FIXME provide hashdata input + gui.showHashDataInputDialog(null, this, "ok"); + } else if (actionCommand.equals("sign")) { + return new String(gui.getPin()); + } else if (actionCommand.equals("ok")) { + gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, + "hashData"); + } + } while (true); + } + + @Override + public SMCCSTALRequestHandler newInstance() { + return new SignRequestHandler(); + } +} diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java new file mode 100644 index 00000000..f2d61e7f --- /dev/null +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java @@ -0,0 +1,105 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc; + +import iaik.me.asn1.ASN1; +import iaik.me.utils.Base64; + +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Vector; + +import org.junit.Ignore; + +@Ignore +public class ASN1Test { + + public static void main(String[] args) throws IOException { + + ClassLoader classLoader = ASN1Test.class.getClassLoader(); + + InputStream stream = classLoader.getResourceAsStream("IdentityLink.bin"); + + if (stream != null) { + + ASN1 identityLink = new ASN1(stream); + System.out.println("BaseId:" + getBaseId(identityLink)); + identityLink = replaceBaseId(identityLink, "test"); + System.out.println("BaseId:" + getBaseId(identityLink)); + + String bpk = "hansi"; + MessageDigest sha = null; + try { + sha = MessageDigest.getInstance("SHA"); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + sha.update((identityLink + "+" + bpk).getBytes()); + String bpkStr = new String(Base64.encode(sha.digest())); + System.out.println("bpk: "+bpkStr); + identityLink = replaceBaseId(identityLink, bpkStr); + System.out.println(getBaseId(identityLink)); + + } else { + System.out.println("Not found."); + } + + } + + private static String getBaseId(ASN1 identityLink) throws IOException { + + if (identityLink.getType() == ASN1.TYPE_SEQUENCE) { + ASN1 personData = identityLink.getElementAt(4); + if (personData.getType() == ASN1.TAG_CONTEXT_SPECIFIC) { + ASN1 physicalPersonData = personData.gvASN1(); + ASN1 baseId = physicalPersonData.getElementAt(0); + return baseId.gvString(); + } + throw new IOException("Invalid structure."); + + } + throw new IOException("Invalid structure."); + + } + + private static ASN1 replaceBaseId(ASN1 identityLink, String newBaseId) + throws IOException { + + ASN1 newIdentityLink = new ASN1(ASN1.TYPE_SEQUENCE, new Vector()); + for (int i = 0; i < identityLink.getSize(); i++) { + ASN1 asn1 = identityLink.getElementAt(i); + if (i == 4 && asn1.getType() == ASN1.TAG_CONTEXT_SPECIFIC) { + ASN1 physicalPersonData = asn1.gvASN1(); + ASN1 newPhysicalPersonData = new ASN1(ASN1.TYPE_SEQUENCE, + new Vector()); + newPhysicalPersonData.addElement(new ASN1(ASN1.TYPE_UTF8_STRING, + newBaseId)); + for (int j = 1; j < physicalPersonData.getSize(); j++) { + newPhysicalPersonData.addElement(physicalPersonData.getElementAt(j)); + } + asn1 = new ASN1(ASN1.TAG_CONTEXT_SPECIFIC, newPhysicalPersonData); + } + newIdentityLink.addElement(asn1); + } + return newIdentityLink; + + } + +} -- cgit v1.2.3 From 35b64892bad13c846f19260311c7625d88cef7a1 Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 5 Sep 2008 13:39:53 +0000 Subject: HashDataInput git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@23 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../main/java/at/gv/egiz/stal/HashDataInput.java | 22 ++ .../at/gv/egiz/stal/HashDataInputCallback.java | 24 -- .../src/main/java/at/gv/egiz/stal/SignRequest.java | 7 +- .../gv/egiz/stal/impl/ByteArrayHashDataInput.java | 47 +++ .../stal/service/GetHashDataInputResponseType.java | 39 ++- smccSTAL/pom.xml | 74 ++--- .../egiz/bku/smccstal/AbstractRequestHandler.java | 139 +++++---- .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 196 ++++++------ .../egiz/bku/smccstal/SMCCSTALRequestHandler.java | 39 ++- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 337 ++++++++++++--------- 10 files changed, 511 insertions(+), 413 deletions(-) create mode 100644 STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java delete mode 100644 STAL/src/main/java/at/gv/egiz/stal/HashDataInputCallback.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java (limited to 'smccSTAL/src') diff --git a/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java b/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java new file mode 100644 index 00000000..2d1e9ce6 --- /dev/null +++ b/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java @@ -0,0 +1,22 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package at.gv.egiz.stal; + +import java.io.InputStream; + +/** + * + * @author clemens + */ +public interface HashDataInput { + + public String getReferenceId(); + + public String getMimeType(); + + public InputStream getHashDataInput(); + +} diff --git a/STAL/src/main/java/at/gv/egiz/stal/HashDataInputCallback.java b/STAL/src/main/java/at/gv/egiz/stal/HashDataInputCallback.java deleted file mode 100644 index f1ccf937..00000000 --- a/STAL/src/main/java/at/gv/egiz/stal/HashDataInputCallback.java +++ /dev/null @@ -1,24 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal; - -import java.io.InputStream; - -public interface HashDataInputCallback { - - InputStream getHashDataInput(String referenceId); -} diff --git a/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java b/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java index 8c996d2c..b1fea0fe 100644 --- a/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java +++ b/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java @@ -16,6 +16,7 @@ */ package at.gv.egiz.stal; +import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -55,7 +56,7 @@ public class SignRequest @XmlElement(name = "SignedInfo", required = true) protected byte[] signedInfo; @XmlTransient - protected HashDataInputCallback hashData; + protected List hashData; /** * Gets the value of the keyIdentifier property. @@ -103,11 +104,11 @@ public class SignRequest this.signedInfo = ((byte[]) value); } - public HashDataInputCallback getHashDataInput() { + public List getHashDataInput() { return hashData; } - public void setHashDataInput(HashDataInputCallback hashData) { + public void setHashDataInput(List hashData) { this.hashData = hashData; } } diff --git a/STALService/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java b/STALService/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java new file mode 100644 index 00000000..1f6e7935 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java @@ -0,0 +1,47 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package at.gv.egiz.stal.impl; + +import at.gv.egiz.stal.HashDataInput; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * + * @author clemens + */ +public class ByteArrayHashDataInput implements HashDataInput { + + protected byte[] hashData; + protected String id; + protected String mimeType; + + public ByteArrayHashDataInput(byte[] hashData, String id, String mimeType) { + if (hashData == null) { + throw new NullPointerException("HashDataInput not provided."); + } + this.hashData = hashData; + this.id = id; + this.mimeType = mimeType; + } + + @Override + public String getReferenceId() { + return id; + } + + @Override + public String getMimeType() { + return mimeType; + } + + @Override + public InputStream getHashDataInput() { + return new ByteArrayInputStream(hashData); + } + + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputResponseType.java index b5f24030..cf8545e9 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputResponseType.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputResponseType.java @@ -23,12 +23,8 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlID; -import javax.xml.bind.annotation.XmlSchemaType; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlValue; -import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; /** @@ -45,7 +41,8 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; * <complexType> * <simpleContent> * <extension base="<http://www.w3.org/2001/XMLSchema>base64Binary"> - * <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}ID" /> + * <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="MimeType" type="{http://www.w3.org/2001/XMLSchema}string" /> * </extension> * </simpleContent> * </complexType> @@ -133,7 +130,8 @@ public class GetHashDataInputResponseType { * <complexType> * <simpleContent> * <extension base="<http://www.w3.org/2001/XMLSchema>base64Binary"> - * <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}ID" /> + * <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="MimeType" type="{http://www.w3.org/2001/XMLSchema}string" /> * </extension> * </simpleContent> * </complexType> @@ -150,10 +148,9 @@ public class GetHashDataInputResponseType { @XmlValue protected byte[] value; @XmlAttribute(name = "ID") - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - @XmlID - @XmlSchemaType(name = "ID") protected String id; + @XmlAttribute(name = "MimeType") + protected String mimeType; /** * Gets the value of the value property. @@ -201,6 +198,30 @@ public class GetHashDataInputResponseType { this.id = value; } + /** + * Gets the value of the mimeType property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMimeType() { + return mimeType; + } + + /** + * Sets the value of the mimeType property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMimeType(String value) { + this.mimeType = value; + } + } } diff --git a/smccSTAL/pom.xml b/smccSTAL/pom.xml index 4af8c6de..8b1a24b0 100644 --- a/smccSTAL/pom.xml +++ b/smccSTAL/pom.xml @@ -1,40 +1,40 @@ - - bku - at.gv.egiz - 1.0-SNAPSHOT - - 4.0.0 - at.gv.egiz - smccSTAL - smcc STAL - 1.0-SNAPSHOT - - - - at.gv.egiz - STAL - 1.0-SNAPSHOT - - - at.gv.egiz - smcc - 1.0-SNAPSHOT - - - at.gv.egiz - BKUCommonGUI - 1.0-SNAPSHOT - - - iaik - iaik_jce_me4se - - - commons-logging - commons-logging - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + bku + at.gv.egiz + 1.0-SNAPSHOT + + 4.0.0 + at.gv.egiz + smccSTAL + smcc STAL + 1.0-SNAPSHOT + + + + at.gv.egiz + STAL + 1.0-SNAPSHOT + + + at.gv.egiz + smcc + 1.0-SNAPSHOT + + + at.gv.egiz + BKUCommonGUI + 1.0-SNAPSHOT + + + iaik + iaik_jce_me4se + + + commons-logging + commons-logging + + \ No newline at end of file diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java index e5afa478..995e2b77 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java @@ -14,73 +14,72 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.bku.smccstal; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.SignatureCard; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; - -public abstract class AbstractRequestHandler implements SMCCSTALRequestHandler, - ActionListener { - private final static Log log = LogFactory - .getLog(AbstractRequestHandler.class); - - protected SignatureCard card; - protected BKUGUIFacade gui; - protected static STALMessageConsumer messageConsumer = null; - protected String actionCommand; - protected boolean actionPerformed = false; - - @Override - public abstract STALResponse handleRequest(STALRequest request); - - @Override - public void init(SignatureCard sc, BKUGUIFacade gui) { - if ((sc == null) || (gui == null)) { - throw new NullPointerException("Parameter must not be set to null"); - } - this.card = sc; - this.gui = gui; - } - - public static void setMessageConsumer(STALMessageConsumer messageConsumer) { - AbstractRequestHandler.messageConsumer = messageConsumer; - } - - protected static void newSTALMessage(String caption, String message) { - if (messageConsumer != null) { - messageConsumer.consumeNewSTALMessage(caption, message); - } - } - - protected synchronized void waitForAction() { - try { - while (!actionPerformed) { - wait(); - } - } catch (InterruptedException e) { - log.info(e); - } - actionPerformed = false; - } - - private synchronized void actionPerformed() { - actionPerformed = true; - notifyAll(); - } - - @Override - public void actionPerformed(ActionEvent e) { - actionCommand = e.getActionCommand(); - actionPerformed(); - } - -} +package at.gv.egiz.bku.smccstal; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +public abstract class AbstractRequestHandler implements SMCCSTALRequestHandler, + ActionListener { + private final static Log log = LogFactory + .getLog(AbstractRequestHandler.class); + + protected SignatureCard card; + protected BKUGUIFacade gui; + protected static STALMessageConsumer messageConsumer = null; + protected String actionCommand; + protected boolean actionPerformed = false; + + @Override + public abstract STALResponse handleRequest(STALRequest request); + + @Override + public void init(SignatureCard sc, BKUGUIFacade gui) { + if ((sc == null) || (gui == null)) { + throw new NullPointerException("Parameter must not be set to null"); + } + this.card = sc; + this.gui = gui; + } + + public static void setMessageConsumer(STALMessageConsumer messageConsumer) { + AbstractRequestHandler.messageConsumer = messageConsumer; + } + + protected static void newSTALMessage(String caption, String message) { + if (messageConsumer != null) { + messageConsumer.consumeNewSTALMessage(caption, message); + } + } + + protected synchronized void waitForAction() { + try { + while (!actionPerformed) { + wait(); + } + } catch (InterruptedException e) { + log.info(e); + } + actionPerformed = false; + } + + private synchronized void actionPerformed() { + actionPerformed = true; + notifyAll(); + } + + @Override + public void actionPerformed(ActionEvent e) { + actionCommand = e.getActionCommand(); + actionPerformed(); + } + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 7bd9e264..56c8340b 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -14,103 +14,99 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.bku.smccstal; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.SignatureCard; -import at.gv.egiz.smcc.util.SMCCHelper; -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.InfoboxReadRequest; -import at.gv.egiz.stal.STAL; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; -import at.gv.egiz.stal.SignRequest; - -public abstract class AbstractSMCCSTAL implements STAL { - private static Log log = LogFactory.getLog(AbstractSMCCSTAL.class); - - protected Locale locale = Locale.getDefault(); - protected SMCCHelper smccHelper = new SMCCHelper(); - protected SignatureCard signatureCard = null; - protected static Map handlerMap = new HashMap(); - - static { - addRequestHandler(InfoboxReadRequest.class, new InfoBoxReadRequestHandler()); - addRequestHandler(SignRequest.class, new SignRequestHandler()); - } - - public AbstractSMCCSTAL() { - } - - /** - * Implementations must assign the signature card within this method. - * - * @return if the user canceled - */ - protected abstract boolean waitForCard(); - - protected abstract BKUGUIFacade getGUI(); - - @Override - public List handleRequest( - List requestList) { - log.debug("Got request list containing " + requestList.size() - + " STAL requests"); - List responseList = new ArrayList(requestList - .size()); - for (STALRequest request : requestList) { - log.info("Processing: " + request); - SMCCSTALRequestHandler handler = null; - handler = handlerMap.get(request.getClass().getSimpleName()); - if (handler != null) { - if (handler.requireCard()) { - if (waitForCard()) { - responseList.add(new ErrorResponse(6001)); - break; - } - } - try { - handler = handler.newInstance(); - handler.init(signatureCard, getGUI()); - responseList.add(handler.handleRequest(request)); - } catch (Exception e) { - log.info("Error while handling STAL request:" + e); - responseList.add(new ErrorResponse(6000)); - } - } else { - log.error("Cannot find a handler for STAL request: " + request); - responseList.add(new ErrorResponse()); - } - } - return responseList; - } - - public static void addRequestHandler(Class id, - SMCCSTALRequestHandler handler) { - log.debug("Registering STAL request handler: " + id.getSimpleName()); - handlerMap.put(id.getSimpleName(), handler); - } - - public static SMCCSTALRequestHandler getRequestHandler( - Class request) { - return handlerMap.get(request.getSimpleName()); - } - - @Override - public void setLocale(Locale locale) { - if (locale == null) { - throw new NullPointerException("Locale must not be set to null"); - } - this.locale = locale; - } -} +package at.gv.egiz.bku.smccstal; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.util.SMCCHelper; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; + +public abstract class AbstractSMCCSTAL implements STAL { + private static Log log = LogFactory.getLog(AbstractSMCCSTAL.class); + + protected Locale locale = Locale.getDefault(); + protected SMCCHelper smccHelper = new SMCCHelper(); + protected SignatureCard signatureCard = null; + protected static Map handlerMap = new HashMap(); + + static { + addRequestHandler(InfoboxReadRequest.class, new InfoBoxReadRequestHandler()); + addRequestHandler(SignRequest.class, new SignRequestHandler()); + } + + /** + * Implementations must assign the signature card within this method. + * + * @return if the user canceled + */ + protected abstract boolean waitForCard(); + + protected abstract BKUGUIFacade getGUI(); + + @Override + public List handleRequest( + List requestList) { + log.debug("Got request list containing " + requestList.size() + + " STAL requests"); + List responseList = new ArrayList(requestList + .size()); + for (STALRequest request : requestList) { + log.info("Processing: " + request); + SMCCSTALRequestHandler handler = null; + handler = handlerMap.get(request.getClass().getSimpleName()); + if (handler != null) { + if (handler.requireCard()) { + if (waitForCard()) { + responseList.add(new ErrorResponse(6001)); + break; + } + } + try { + handler = handler.newInstance(); + handler.init(signatureCard, getGUI()); + responseList.add(handler.handleRequest(request)); + } catch (Exception e) { + log.info("Error while handling STAL request:" + e); + responseList.add(new ErrorResponse(6000)); + } + } else { + log.error("Cannot find a handler for STAL request: " + request); + responseList.add(new ErrorResponse()); + } + } + return responseList; + } + + public static void addRequestHandler(Class id, + SMCCSTALRequestHandler handler) { + log.debug("Registering STAL request handler: " + id.getSimpleName()); + handlerMap.put(id.getSimpleName(), handler); + } + + public static SMCCSTALRequestHandler getRequestHandler( + Class request) { + return handlerMap.get(request.getSimpleName()); + } + + @Override + public void setLocale(Locale locale) { + if (locale == null) { + throw new NullPointerException("Locale must not be set to null"); + } + this.locale = locale; + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java index 7badb2a0..6f303f76 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java @@ -14,23 +14,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.bku.smccstal; - - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.SignatureCard; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; - -public interface SMCCSTALRequestHandler { - - public void init(SignatureCard sc, BKUGUIFacade gui); - - public STALResponse handleRequest(STALRequest request); - - public boolean requireCard(); - - public SMCCSTALRequestHandler newInstance(); - -} +package at.gv.egiz.bku.smccstal; + + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +public interface SMCCSTALRequestHandler { + + public void init(SignatureCard sc, BKUGUIFacade gui); + + public STALResponse handleRequest(STALRequest request); + + public boolean requireCard(); + + public SMCCSTALRequestHandler newInstance(); + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 6ae4fa01..2fe77c5d 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -1,151 +1,188 @@ /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.bku.smccstal; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.smcc.SignatureCard; -import at.gv.egiz.smcc.SignatureCardException; -import at.gv.egiz.smcc.SignatureCard.KeyboxName; -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; -import at.gv.egiz.stal.SignRequest; -import at.gv.egiz.stal.SignResponse; -import at.gv.egiz.stal.signedinfo.ObjectFactory; -import at.gv.egiz.stal.signedinfo.SignedInfoType; -import at.gv.egiz.stal.util.JCEAlgorithmNames; - -public class SignRequestHandler extends AbstractRequestHandler implements - PINProvider { - private static Log log = LogFactory.getLog(SignRequestHandler.class); - - private static JAXBContext jaxbContext; - - static { - try { - jaxbContext = JAXBContext.newInstance(ObjectFactory.class.getPackage() - .getName()); - } catch (JAXBException e) { - log.fatal("Cannot init jaxbContext", e); - } - } - - private int retryCounter = 0; - - public SignRequestHandler() { - } - - @SuppressWarnings("unchecked") - @Override - public STALResponse handleRequest(STALRequest request) { - if (request instanceof SignRequest) { - SignRequest signReq = (SignRequest) request; - newSTALMessage("Message.RequestCaption", "Message.SignRequest"); - try { - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - InputStream is = new ByteArrayInputStream(signReq.getSignedInfo()); - JAXBElement signedInfo = (JAXBElement) unmarshaller - .unmarshal(is); - String signatureMethod = signedInfo.getValue().getSignatureMethod() - .getAlgorithm(); - log.debug("Found signature method: " + signatureMethod); - String jceName = JCEAlgorithmNames.getJCEHashName(signatureMethod); - if (jceName == null) { - log.error("Hash algorithm not supported:"); - return new ErrorResponse(1000); - } - MessageDigest md = MessageDigest.getInstance(jceName); - md.update(signReq.getSignedInfo()); - KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq - .getKeyIdentifier()); - byte[] resp = card.createSignature(md.digest(), kb, this); - if (resp == null) { - return new ErrorResponse(6001); - } - SignResponse stalResp = new SignResponse(); - stalResp.setSignatureValue(resp); - return stalResp; - } catch (CancelledException cx) { - log.debug("User cancelled request"); - return new ErrorResponse(6001); - } catch (SignatureCardException e) { - log.error("Error while creating signature: " + e); - return new ErrorResponse(4000); - } catch (JAXBException e) { - log.error("Cannot unmarshall signed info", e); - return new ErrorResponse(1000); - } catch (NoSuchAlgorithmException e) { - log.error(e); - return new ErrorResponse(1000); - } - } else { - log.fatal("Got unexpected STAL request: " + request); - return new ErrorResponse(1000); - } - } - - @Override - public boolean requireCard() { - return true; - } - - @Override - public String providePIN(PINSpec spec, int retries) { - if (retryCounter++ > 0) { - log.info("PIN wrong retrying ..."); - gui.showSignaturePINRetryDialog(spec, retries, this, "sign", this, - "cancel", this, "hashData"); - } else { - gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, - "hashData"); - } - do { - waitForAction(); - if (actionCommand.equals("cancel")) { - return null; - } else if (actionCommand.equals("hashData")) { - // FIXME provide hashdata input - gui.showHashDataInputDialog(null, this, "ok"); - } else if (actionCommand.equals("sign")) { - return new String(gui.getPin()); - } else if (actionCommand.equals("ok")) { - gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, - "hashData"); - } - } while (true); - } - - @Override - public SMCCSTALRequestHandler newInstance() { - return new SignRequestHandler(); - } -} + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.SignatureCard.KeyboxName; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.SignResponse; +import at.gv.egiz.stal.signedinfo.ObjectFactory; +import at.gv.egiz.stal.signedinfo.ReferenceType; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import at.gv.egiz.stal.util.JCEAlgorithmNames; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is NOT thread-safe. + * handleRequest() sets the SignedInfo which is used in providePIN. + */ +public class SignRequestHandler extends AbstractRequestHandler implements + PINProvider { + + private static Log log = LogFactory.getLog(SignRequestHandler.class); + private static JAXBContext jaxbContext; + + + static { + try { + jaxbContext = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName()); + } catch (JAXBException e) { + log.fatal("Cannot init jaxbContext", e); + } + } + /** the SignedInfo of the current SignRequest */ + protected SignedInfoType signedInfo; + protected List hashDataInputs; + + private int retryCounter = 0; + + @SuppressWarnings("unchecked") + @Override + public STALResponse handleRequest(STALRequest request) { + if (request instanceof SignRequest) { + SignRequest signReq = (SignRequest) request; + newSTALMessage("Message.RequestCaption", "Message.SignRequest"); + try { + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + InputStream is = new ByteArrayInputStream(signReq.getSignedInfo()); + JAXBElement si = (JAXBElement) unmarshaller.unmarshal(is); + signedInfo = si.getValue(); + String signatureMethod = signedInfo.getSignatureMethod().getAlgorithm(); + log.debug("Found signature method: " + signatureMethod); + String jceName = JCEAlgorithmNames.getJCEHashName(signatureMethod); + if (jceName == null) { + log.error("Hash algorithm not supported:"); + return new ErrorResponse(1000); + } + MessageDigest md = MessageDigest.getInstance(jceName); + md.update(signReq.getSignedInfo()); + KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); + byte[] resp = card.createSignature(md.digest(), kb, this); + if (resp == null) { + return new ErrorResponse(6001); + } + SignResponse stalResp = new SignResponse(); + stalResp.setSignatureValue(resp); + return stalResp; + } catch (CancelledException cx) { + log.debug("User cancelled request"); + return new ErrorResponse(6001); + } catch (SignatureCardException e) { + log.error("Error while creating signature: " + e); + return new ErrorResponse(4000); + } catch (JAXBException e) { + log.error("Cannot unmarshall signed info", e); + return new ErrorResponse(1000); + } catch (NoSuchAlgorithmException e) { + log.error(e); + return new ErrorResponse(1000); + } finally { + signedInfo = null; + } + } else { + log.fatal("Got unexpected STAL request: " + request); + return new ErrorResponse(1000); + } + } + + @Override + public boolean requireCard() { + return true; + } + + @Override + public String providePIN(PINSpec spec, int retries) { + if (retryCounter++ > 0) { + log.info("PIN wrong retrying ..."); + gui.showSignaturePINRetryDialog(spec, retries, this, "sign", this, + "cancel", this, "hashData"); + } else { + gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, + "hashData"); + } + do { + waitForAction(); + if (actionCommand.equals("cancel")) { + return null; + } else if (actionCommand.equals("hashData")) { + if (signedInfo != null) { + try { + gui.showWaitDialog(null); + if (hashDataInputs == null) { + hashDataInputs = getHashDataInputs(signedInfo.getReference()); + } + gui.showHashDataInputDialog(hashDataInputs, this, "ok"); + waitForAction(); + gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, + "hashData"); + } catch (Exception ex) { + //FIXME localize messages + log.error("Failed to obtain HashDataInputs: " + ex.getMessage()); + gui.showErrorDialog("Failed to obtain HashDataInputs: " + ex.getMessage(), this, "ok"); + } + } else { + //FIXME get all hashdatainputs + gui.showErrorDialog("Failed to obtain HashDataInputs: No dsig:SignedInfo provided.", this, "ok"); + } + } else if (actionCommand.equals("sign")) { + return new String(gui.getPin()); + } else if (actionCommand.equals("ok")) { + gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, + "hashData"); + } + } while (true); + } + + @Override + public SMCCSTALRequestHandler newInstance() { + return new SignRequestHandler(); + } + + /** + * override by subclass + * @return + */ + protected List getHashDataInputs(List signedReferences) throws Exception { + //TODO + log.warn("Return empty HashDataInput"); + return new ArrayList(); + } +} -- cgit v1.2.3 From d3698ed2a4f129e5af970f072bc79bb8226d7765 Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 5 Sep 2008 15:41:19 +0000 Subject: Text HashDataInput git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@24 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/bku/gui/BKUGUI.java | 111 ++++++++++++++++++++- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 34 ++++--- .../stal/service/impl/STALRequestBrokerImpl.java | 2 +- .../gv/egiz/stal/service/impl/STALServiceImpl.java | 2 +- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 2 +- 5 files changed, 128 insertions(+), 23 deletions(-) (limited to 'smccSTAL/src') diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java index 0ad09c70..5175b45f 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java @@ -29,15 +29,22 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; import java.text.MessageFormat; import java.util.List; import java.util.Locale; import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.GroupLayout; @@ -48,6 +55,8 @@ import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPasswordField; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; import javax.swing.LayoutStyle; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileFilter; @@ -677,11 +686,44 @@ public class BKUGUI implements BKUGUIFacade { if (signedReferences != null && signedReferences.size() == 1) { - HashDataInput signedRef = signedReferences.get(0); -// if ("text/plain".equals(signedRef.getMimeType())) { -// } else { + final HashDataInput signedRef = signedReferences.get(0); + if ("text/plain".equals(signedRef.getMimeType())) { + //TODO get encoding from mimetype + //read directly to byte[] since hashDataIS is backed by byte[] ? + ByteArrayOutputStream baos = null; + try { + String refId = signedRef.getReferenceId(); + InputStream hashDataIS = signedRef.getHashDataInput(); + if (hashDataIS == null) { + showErrorDialog("Failed to obtain HashDataInput for reference " + refId, okListener, okCommand); + } else { + baos = new ByteArrayOutputStream(hashDataIS.available()); + int c; + while ((c = hashDataIS.read()) != -1) { + baos.write(c); + } + String text = baos.toString("UTF-8"); + + ActionListener al = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + showSaveHashDataInputDialog(signedRef, okListener, okCommand); + } + }; + showPlainTextHashDataInputDialog(text, refId, okListener, okCommand, al, "save"); + } + } catch (IOException ex) { + showErrorDialog("Failed to read HashDataInput for reference " + signedRef.getReferenceId() + ": " + ex.getMessage(), okListener, okCommand); + } finally { + try { + baos.close(); + } catch (IOException ex) { + } + } + } else { showSaveHashDataInputDialog(signedRef, okListener, okCommand); -// } + } } else { mainPanel.removeAll(); @@ -723,7 +765,66 @@ public class BKUGUI implements BKUGUIFacade { }); } - + private void showPlainTextHashDataInputDialog(String text, String refId, ActionListener cancelListener, String cancelCommand, ActionListener saveListener, String saveCommand) { + mainPanel.removeAll(); + buttonPanel.removeAll(); + + titleLabel.setText(messages.getString(TITLE_HASHDATA)); + + JLabel refIdLabel = new JLabel(); + refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + String refIdLabelPattern = messages.getString(MESSAGE_HASHDATA); + refIdLabel.setText(MessageFormat.format(refIdLabelPattern, new Object[] {refId} )); + + JScrollPane hashDataScrollPane = new JScrollPane(); + JTextArea hashDataTextArea = new JTextArea(text); + hashDataTextArea.setEditable(false); + hashDataTextArea.setColumns(20); + hashDataTextArea.setRows(3); + hashDataScrollPane.setViewportView(hashDataTextArea); + + + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont()); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); + cancelButton.setActionCommand(cancelCommand); + cancelButton.addActionListener(cancelListener); + + JButton saveButton = new JButton(); + saveButton.setFont(saveButton.getFont()); + saveButton.setText(messages.getString(BUTTON_SAVE)); + saveButton.setActionCommand(saveCommand); + saveButton.addActionListener(saveListener); + + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + mainPanelLayout.setHorizontalGroup( + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(mainPanelLayout.createSequentialGroup() + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(refIdLabel) + .addComponent(hashDataScrollPane, GroupLayout.PREFERRED_SIZE, PREF_SIZE_PINFIELD, Short.MAX_VALUE)) + .addContainerGap())); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(refIdLabel) + .addGap(refIdLabel.getFont().getSize()) + .addComponent(hashDataScrollPane) + .addGap(refIdLabel.getFont().getSize()))); + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + buttonPanelLayout.setHorizontalGroup( + buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(GroupLayout.Alignment.TRAILING, buttonPanelLayout.createSequentialGroup().addContainerGap(15, Short.MAX_VALUE).addComponent(saveButton).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(cancelButton).addContainerGap())); + buttonPanelLayout.setVerticalGroup( + buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(saveButton).addComponent(cancelButton))); + + contentPanel.validate(); + } private void showSaveHashDataInputDialog(HashDataInput signedRef, ActionListener okListener, String okCommand) { String dir = System.getProperty("user.home"); diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index a251be55..e2f478c9 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -86,7 +86,7 @@ public class BKUGUIWorker implements Runnable { @Override public String getMimeType() { - return "text/xml"; + return "text/plain"; } @Override @@ -104,13 +104,13 @@ public class BKUGUIWorker implements Runnable { // // Thread.sleep(2000); - gui.showInsertCardDialog(cancelListener, "cancel"); - - Thread.sleep(2000); - - gui.showCardNotSupportedDialog(cancelListener, "cancel"); - - Thread.sleep(2000); +// gui.showInsertCardDialog(cancelListener, "cancel"); +// +// Thread.sleep(2000); +// +// gui.showCardNotSupportedDialog(cancelListener, "cancel"); +// +// Thread.sleep(2000); // PINSpec cardPinSpec = new PINSpec(4, 4, "[0-9]", "Karten-PIN"); // @@ -119,19 +119,23 @@ public class BKUGUIWorker implements Runnable { // Thread.sleep(2000); // -// gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); -// -// Thread.sleep(2000); -// -// gui.showSignaturePINRetryDialog(signPinSpec, 2, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); -// -// Thread.sleep(2000); + gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); + + Thread.sleep(2000); + + gui.showSignaturePINRetryDialog(signPinSpec, 2, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); + + Thread.sleep(2000); //// // gui.showErrorDialog("Testfehler occured", null, null); // // Thread.sleep(2000); // // gui.showErrorDialog("Testfehler occured"); + + +// gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save"); +// Thread.sleep(2000); } catch (InterruptedException ex) { ex.printStackTrace(); diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java index 9601d39c..d206913d 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java @@ -95,7 +95,7 @@ public class STALRequestBrokerImpl implements STALRequestBroker { currentHashDataInput = null; for (STALRequest request : requests) { if (request instanceof SignRequest) { - log.trace("Received SignRequest, keep HashDataInput callback."); + log.trace("Received SignRequest, keep HashDataInput."); currentHashDataInput = ((SignRequest) request).getHashDataInput(); break; } else if (request instanceof QuitRequest) { diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java index f0df22ea..f4cdc7d2 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java @@ -1,4 +1,4 @@ -/* + /* * Copyright 2008 Federal Chancellery Austria and * Graz University of Technology * diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 2fe77c5d..1f84300a 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -146,7 +146,7 @@ public class SignRequestHandler extends AbstractRequestHandler implements if (signedInfo != null) { try { gui.showWaitDialog(null); - if (hashDataInputs == null) { + if (hashDataInputs == null || hashDataInputs.size() == 0) { hashDataInputs = getHashDataInputs(signedInfo.getReference()); } gui.showHashDataInputDialog(hashDataInputs, this, "ok"); -- cgit v1.2.3 From 3794536434fdbb06067eddcfd248898ce85f85a1 Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 12 Sep 2008 13:06:34 +0000 Subject: gui 0.2 git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@34 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/bku/online/applet/BKUApplet.java | 102 ++- .../src/main/java/at/gv/egiz/bku/gui/BKUGUI.java | 885 ++++++++++----------- .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 2 + .../at/gv/egiz/bku/gui/HashDataTableModel.java | 71 ++ .../main/java/at/gv/egiz/bku/gui/MimeFilter.java | 98 +++ .../main/java/at/gv/egiz/bku/gui/PinDocument.java | 58 ++ .../at/gv/egiz/bku/gui/Messages.properties | 15 +- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 276 +++---- BKUOnline/pom.xml | 13 +- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 6 +- 10 files changed, 840 insertions(+), 686 deletions(-) create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/MimeFilter.java create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java index 8289f30b..c7df0871 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java @@ -34,63 +34,59 @@ import at.gv.egiz.bku.gui.BKUGUIFactory; */ public class BKUApplet extends JApplet { - private static Log log = LogFactory.getLog(BKUApplet.class); + private static Log log = LogFactory.getLog(BKUApplet.class); + public final static String RESOURCE_BUNDLE_BASE = "at/gv/egiz/bku/online/applet/Messages"; + public final static String LOCALE_PARAM_KEY = "Locale"; + public final static String LOGO_URL_KEY = "LogoURL"; + public final static String WSDL_URL = "WSDL_URL"; + public final static String SESSION_ID = "SessionID"; + protected ResourceBundle resourceBundle; + protected BKUWorker worker; + protected Thread workerThread; - public final static String RESOURCE_BUNDLE_BASE = "at/gv/egiz/bku/online/applet/Messages"; + public BKUApplet() { + } - public final static String LOCALE_PARAM_KEY = "Locale"; - public final static String LOGO_URL_KEY = "LogoURL"; - public final static String WSDL_URL = "WSDL_URL"; - public final static String SESSION_ID = "SessionID"; + public void init() { + log.debug("Called init()"); + HttpsURLConnection.setDefaultSSLSocketFactory(InternalSSLSocketFactory.getInstance()); + String localeString = getMyAppletParameter(LOCALE_PARAM_KEY); + if (localeString != null) { + resourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE_BASE, + new Locale(localeString)); + } else { + resourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE_BASE); + } + BKUGUIFacade gui = BKUGUIFactory.createGUI(); + gui.init(getContentPane(), localeString); + worker = new BKUWorker(gui, this, resourceBundle); + } - protected ResourceBundle resourceBundle; - protected BKUWorker worker; - protected Thread workerThread; + public void start() { + log.debug("Called start()"); + workerThread = new Thread(worker); + workerThread.start(); + } - public BKUApplet() { - } + public void stop() { + log.debug("Called stop()"); + if ((workerThread != null) && (workerThread.isAlive())) { + workerThread.interrupt(); + } + } - public void init() { - log.debug("Called init()"); - HttpsURLConnection.setDefaultSSLSocketFactory(InternalSSLSocketFactory - .getInstance()); - String localeString = getMyAppletParameter(LOCALE_PARAM_KEY); - if (localeString != null) { - resourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE_BASE, - new Locale(localeString)); - } else { - resourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE_BASE); - } - BKUGUIFacade gui = BKUGUIFactory.createGUI(); - gui.init(getContentPane(), localeString); - worker = new BKUWorker(gui, this, resourceBundle); - } + public void destroy() { + log.debug("Called destroy()"); + } - public void start() { - log.debug("Called start()"); - workerThread = new Thread(worker); - workerThread.start(); - } - - public void stop() { - log.debug("Called stop()"); - if ((workerThread != null) && (workerThread.isAlive())) { - workerThread.interrupt(); - } - } - - public void destroy() { - log.debug("Called destroy()"); - } - - /** - * Applet configuration parameters - * - * @param paramKey - * @return - */ - public String getMyAppletParameter(String paramKey) { - log.info("Getting parameter: " + paramKey + ": " + getParameter(paramKey)); - return getParameter(paramKey); - } + /** + * Applet configuration parameters + * + * @param paramKey + * @return + */ + public String getMyAppletParameter(String paramKey) { + log.info("Getting parameter: " + paramKey + ": " + getParameter(paramKey)); + return getParameter(paramKey); + } } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java index 044e6927..584dba1a 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java @@ -27,6 +27,7 @@ import java.awt.Component; import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; +import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; @@ -75,13 +76,11 @@ import org.apache.commons.logging.LogFactory; * @author clemens */ public class BKUGUI implements BKUGUIFacade { - + private static final Log log = LogFactory.getLog(BKUGUI.class); public static final String MESSAGES_BUNDLE = "at/gv/egiz/bku/gui/Messages"; public static final String LOGO_RESOURCE = "/images/logo.png"; -// public static final int MAIN_PANEL_WIDTH = 100; -// public static final int MAIN_PANEL_HEIGHT = 20; -// public static final int PREF_SIZE_PINFIELD = 118; + public static final String HASHDATA_FONT = "Monospaced"; public static final Color ERROR_COLOR = Color.RED; public static final Color HYPERLINK_COLOR = Color.BLUE; private static final String TITLE_WELCOME = "title.welcome"; @@ -94,6 +93,7 @@ public class BKUGUI implements BKUGUIFacade { private static final String TITLE_WAIT = "title.wait"; private static final String TITLE_HASHDATA = "title.hashdata"; private static final String WINDOWTITLE_SAVE = "windowtitle.save"; + private static final String WINDOWTITLE_SAVEDIR = "windowtitle.savedir"; private static final String WINDOWTITLE_OVERWRITE = "windowtitle.overwrite"; private static final String MESSAGE_WAIT = "message.wait"; private static final String MESSAGE_INSERTCARD = "message.insertcard"; @@ -104,19 +104,13 @@ public class BKUGUI implements BKUGUIFacade { private static final String MESSAGE_OVERWRITE = "message.overwrite"; private static final String LABEL_PIN = "label.pin"; private static final String LABEL_PINSIZE = "label.pinsize"; - private static final String ERROR_HASHDATA = "error.hashdata"; + private static final String ERROR_NO_HASHDATA = "error.no.hashdata"; private static final String BUTTON_OK = "button.ok"; private static final String BUTTON_CANCEL = "button.cancel"; private static final String BUTTON_BACK = "button.back"; private static final String BUTTON_SIGN = "button.sign"; private static final String BUTTON_SAVE = "button.save"; - private static final String MIMETYPE_DESC_XML = "mimetype.desc.xml"; - private static final String MIMETYPE_DESC_HTML = "mimetype.desc.html"; - private static final String MIMETYPE_DESC_XHTML = "mimetype.desc.xhtml"; - private static final String MIMETYPE_DESC_TXT = "mimetype.desc.txt"; - private static final String MIMETYPE_DESC_PDF = "mimetype.desc.pdf"; - private static final String MIMETYPE_DESC_BIN = "mimetype.desc.bin"; private static final String SAVE_HASHDATAINPUT_PREFIX = "save.hashdatainput.prefix"; protected Container contentPane; protected ResourceBundle messages; @@ -132,11 +126,11 @@ public class BKUGUI implements BKUGUIFacade { /** remember the pinfield to return to worker */ protected JPasswordField pinField; - protected JButton okButton; - protected JButton cancelButton; - protected JButton signButton; - protected JButton saveButton; - protected JButton backButton; +// protected JButton okButton; +// protected JButton cancelButton; +// protected JButton signButton; +// protected JButton saveButton; +// protected JButton backButton; protected int buttonSize; private static final int CHECKBOX_WIDTH = new JCheckBox().getPreferredSize().width; @@ -216,28 +210,43 @@ public class BKUGUI implements BKUGUIFacade { java.awt.Font.BOLD, titleLabel.getFont().getSize() + 2)); // titleLabel.setForeground(defaultForground); - okButton = new JButton(); - okButton.setText(messages.getString(BUTTON_OK)); - cancelButton = new JButton(); - cancelButton.setText(messages.getString(BUTTON_CANCEL)); - signButton = new JButton(); - signButton.setText(messages.getString(BUTTON_SIGN)); - backButton = new JButton(); - backButton.setText(messages.getString(BUTTON_BACK)); - saveButton = new JButton(); - saveButton.setText(messages.getString(BUTTON_SAVE)); +// okButton = new JButton(); +// okButton.setText(messages.getString(BUTTON_OK)); +// cancelButton = new JButton(); +// cancelButton.setText(messages.getString(BUTTON_CANCEL)); +// signButton = new JButton(); +// signButton.setText(messages.getString(BUTTON_SIGN)); +// backButton = new JButton(); +// backButton.setText(messages.getString(BUTTON_BACK)); +// saveButton = new JButton(); +// saveButton.setText(messages.getString(BUTTON_SAVE)); // contentPanelLayout.linkSize(cancelButton, okButton, signButton, backButton, saveButton); - if (okButton.getPreferredSize().width > buttonSize) - buttonSize = okButton.getPreferredSize().width; - if (cancelButton.getPreferredSize().width > buttonSize) - buttonSize = cancelButton.getPreferredSize().width; - if (signButton.getPreferredSize().width > buttonSize) - buttonSize = signButton.getPreferredSize().width; - if (backButton.getPreferredSize().width > buttonSize) - buttonSize = backButton.getPreferredSize().width; - if (saveButton.getPreferredSize().width > buttonSize) - buttonSize = saveButton.getPreferredSize().width; + JButton b = new JButton(); + b.setText(messages.getString(BUTTON_CANCEL)); + if (b.getPreferredSize().width > buttonSize) + buttonSize = b.getPreferredSize().width; + b.setText(messages.getString(BUTTON_OK)); + if (b.getPreferredSize().width > buttonSize) + buttonSize = b.getPreferredSize().width; + b.setText(messages.getString(BUTTON_SIGN)); + if (b.getPreferredSize().width > buttonSize) + buttonSize = b.getPreferredSize().width; + b.setText(messages.getString(BUTTON_BACK)); + if (b.getPreferredSize().width > buttonSize) + buttonSize = b.getPreferredSize().width; + b.setText(messages.getString(BUTTON_SAVE)); + if (b.getPreferredSize().width > buttonSize) + buttonSize = b.getPreferredSize().width; + +// if (cancelButton.getPreferredSize().width > buttonSize) +// buttonSize = cancelButton.getPreferredSize().width; +// if (signButton.getPreferredSize().width > buttonSize) +// buttonSize = signButton.getPreferredSize().width; +// if (backButton.getPreferredSize().width > buttonSize) +// buttonSize = backButton.getPreferredSize().width; +// if (saveButton.getPreferredSize().width > buttonSize) +// buttonSize = saveButton.getPreferredSize().width; GroupLayout headerPanelLayout = new GroupLayout(headerPanel); @@ -349,6 +358,8 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_INSERTCARD)); + JButton cancelButton = new JButton(); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); cancelButton.addActionListener(cancelListener); cancelButton.setActionCommand(cancelCommand); @@ -400,6 +411,8 @@ public class BKUGUI implements BKUGUIFacade { // mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(errorMsgLabel)); + JButton cancelButton = new JButton(); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); cancelButton.addActionListener(cancelListener); cancelButton.setActionCommand(cancelCommand); @@ -439,9 +452,13 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_RETRY)); } + JButton cancelButton = new JButton(); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); cancelButton.setActionCommand(cancelCommand); cancelButton.addActionListener(cancelListener); + JButton okButton = new JButton(); + okButton.setText(messages.getString(BUTTON_OK)); okButton.setEnabled(false); okButton.setActionCommand(okCommand); okButton.addActionListener(okListener); @@ -592,9 +609,13 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_RETRY)); } + JButton cancelButton = new JButton(); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); cancelButton.setActionCommand(cancelCommand); cancelButton.addActionListener(cancelListener); + JButton signButton = new JButton(); + signButton.setText(messages.getString(BUTTON_SIGN)); signButton.setEnabled(false); signButton.setActionCommand(signCommand); signButton.addActionListener(signListener); @@ -764,6 +785,8 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(errorMsgLabel)); + JButton okButton = new JButton(); + okButton.setText(messages.getString(BUTTON_OK)); okButton.setActionCommand(okCommand); okButton.addActionListener(okListener); @@ -790,343 +813,386 @@ public class BKUGUI implements BKUGUIFacade { @Override public void showErrorDialog(final String errorMsg) { - SwingUtilities.invokeLater(new Runnable() { + SwingUtilities.invokeLater(new Runnable() { - public void run() { - mainPanel.removeAll(); - buttonPanel.removeAll(); + @Override + public void run() { + mainPanel.removeAll(); + buttonPanel.removeAll(); - titleLabel.setText(messages.getString(TITLE_ERROR)); + titleLabel.setText(messages.getString(TITLE_ERROR)); // titleLabel.setForeground(defaultForground); - JLabel errorMsgLabel = new JLabel(); - errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - errorMsgLabel.setText("" + errorMsg + ""); - errorMsgLabel.setForeground(ERROR_COLOR); + JLabel errorMsgLabel = new JLabel(); + errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + errorMsgLabel.setText("" + errorMsg + ""); + errorMsgLabel.setForeground(ERROR_COLOR); - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() + mainPanelLayout.setHorizontalGroup( + mainPanelLayout.createSequentialGroup() // mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(errorMsgLabel) - .addContainerGap()); //, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(errorMsgLabel)); + .addComponent(errorMsgLabel) + .addContainerGap()); //, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(errorMsgLabel)); - contentPanel.validate(); - } - }); + contentPanel.validate(); + } + }); } @Override public void showHashDataInputDialog(final List signedReferences, final ActionListener okListener, final String okCommand) { - SwingUtilities.invokeLater(new Runnable() { + + if (signedReferences == null) { + showErrorDialog(messages.getString(ERROR_NO_HASHDATA), okListener, okCommand); + } + + if (signedReferences.size() == 1) { + +// final HashDataInput signedRef = signedReferences.get(0); + + if ("text/plain".equals(signedReferences.get(0).getMimeType())) { + + ActionListener saveHashDataListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + showSaveHashDataInputDialog(signedReferences, okListener, okCommand); + } + }; + String hashDataText = getText(signedReferences.get(0)); + if (hashDataText != null) { + showPlainTextHashDataInputDialog(hashDataText, saveHashDataListener, "save", okListener, okCommand); + } else { + showErrorDialog(messages.getString(ERROR_NO_HASHDATA), okListener, okCommand); + } + + } else { + showSaveHashDataInputDialog(signedReferences, okListener, okCommand); + } + + } else { - @Override - public void run() { + final HashDataTableModel tableModel = new HashDataTableModel(signedReferences); - if (signedReferences != null && signedReferences.size() == 1) { - - final HashDataInput signedRef = signedReferences.get(0); - if ("text/plain".equals(signedRef.getMimeType())) { - //TODO get encoding from mimetype - //read directly to byte[] since hashDataIS is backed by byte[] ? - ByteArrayOutputStream baos = null; - try { - String refId = signedRef.getReferenceId(); - InputStream hashDataIS = signedRef.getHashDataInput(); - if (hashDataIS == null) { - showErrorDialog("Failed to obtain HashDataInput for reference " + refId, okListener, okCommand); - } else { - baos = new ByteArrayOutputStream(hashDataIS.available()); - int c; - while ((c = hashDataIS.read()) != -1) { - baos.write(c); - } - String text = baos.toString("UTF-8"); - - ActionListener al = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - showSaveHashDataInputDialog(signedRef, okListener, okCommand); - } - }; - showPlainTextHashDataInputDialog(text, refId, okListener, okCommand, al, "save"); - } - } catch (IOException ex) { - showErrorDialog("Failed to read HashDataInput for reference " + signedRef.getReferenceId() + ": " + ex.getMessage(), okListener, okCommand); - } finally { - try { - baos.close(); - } catch (IOException ex) { - } - } - } else { - showSaveHashDataInputDialog(signedRef, okListener, okCommand); - } + ActionListener saveHashDataListener = new ActionListener() { - } else if (signedReferences != null && signedReferences.size() > 1) { - final HashDataTableModel tableModel = new HashDataTableModel(signedReferences); - - ActionListener al = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - List selection = tableModel.getSelectedReferenceIds(); - StringBuilder sb = new StringBuilder("Not implemented yet. \n"); - for (String string : selection) { - sb.append(string); - sb.append('\n'); - } - showErrorDialog(sb.toString(), okListener, okCommand); -// showSaveHashDataInputDialog(signedRef, okListener, okCommand); - } - }; - showMultipleHashDataInputDialog(tableModel, okListener, okCommand, al, "save"); - } else { - showErrorDialog(messages.getString(ERROR_HASHDATA), okListener, okCommand); - } + @Override + public void actionPerformed(ActionEvent e) { + showSaveHashDataInputDialog(tableModel.getSelectedHashData(), okListener, okCommand); } - }); + }; + showMultipleHashDataInputDialog(tableModel, okListener, okCommand, saveHashDataListener, "save"); + } + } + + private static String getText(HashDataInput hdi) { + ByteArrayOutputStream baos = null; + try { + InputStream hashDataIS = hdi.getHashDataInput(); + if (hashDataIS == null) { + log.error("No HashDataInput stream for reference " + hdi.getReferenceId()); + return null; + } else { + baos = new ByteArrayOutputStream(hashDataIS.available()); + int c; + while ((c = hashDataIS.read()) != -1) { + baos.write(c); + } + return baos.toString("UTF-8"); + } + } catch (IOException ex) { + log.error("Failed to read HashDataInput for reference " + hdi.getReferenceId() + ": " + ex.getMessage()); + return null; + } finally { + try { + baos.close(); + } catch (IOException ex) { + } + } } - private void showPlainTextHashDataInputDialog(String text, String refId, ActionListener cancelListener, String cancelCommand, ActionListener saveListener, String saveCommand) { - mainPanel.removeAll(); - buttonPanel.removeAll(); + private void showPlainTextHashDataInputDialog(final String hashDataText, final ActionListener saveListener, final String saveCommand, final ActionListener cancelListener, final String cancelCommand) { + SwingUtilities.invokeLater(new Runnable() { - titleLabel.setText(messages.getString(TITLE_HASHDATA)); + @Override + public void run() { + mainPanel.removeAll(); + buttonPanel.removeAll(); + + titleLabel.setText(messages.getString(TITLE_HASHDATA)); + + JLabel refIdLabel = new JLabel(); + refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + refIdLabel.setText(messages.getString(MESSAGE_HASHDATA)); //MessageFormat.format(refIdLabelPattern, new Object[]{refId})); + + JScrollPane hashDataScrollPane = new JScrollPane(); + JTextArea hashDataTextArea = new JTextArea(hashDataText); + hashDataTextArea.setEditable(false); + hashDataTextArea.setColumns(1); + hashDataTextArea.setRows(1); + hashDataTextArea.setFont(new Font(HASHDATA_FONT, hashDataTextArea.getFont().getStyle(), hashDataTextArea.getFont().getSize())); + hashDataScrollPane.setViewportView(hashDataTextArea); + + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + mainPanelLayout.setHorizontalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(refIdLabel) + .addComponent(hashDataScrollPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addComponent(refIdLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(hashDataScrollPane, 0, GroupLayout.PREFERRED_SIZE, hashDataTextArea.getPreferredSize().height+3)); + + + + // GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + // mainPanel.setLayout(mainPanelLayout); + // + // mainPanelLayout.setHorizontalGroup( + // mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(mainPanelLayout.createSequentialGroup().addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(refIdLabel).addComponent(hashDataScrollPane, GroupLayout.PREFERRED_SIZE, PREF_SIZE_PINFIELD, Short.MAX_VALUE)).addContainerGap())); + // + // mainPanelLayout.setVerticalGroup( + // mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(mainPanelLayout.createSequentialGroup().addComponent(refIdLabel).addGap(refIdLabel.getFont().getSize()).addComponent(hashDataScrollPane).addGap(refIdLabel.getFont().getSize()))); + + JButton backButton = new JButton(); + backButton.setText(messages.getString(BUTTON_BACK)); + backButton.setActionCommand(cancelCommand); + backButton.addActionListener(cancelListener); + + JButton saveButton = new JButton(); + saveButton.setText(messages.getString(BUTTON_SAVE)); + saveButton.setActionCommand(saveCommand); + saveButton.addActionListener(saveListener); + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + // buttonPanelLayout.linkSize(cancelButton, okButton, signButton, backButton, saveButton); + buttonPanelLayout.setHorizontalGroup( + buttonPanelLayout.createSequentialGroup() + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addContainerGap()); + buttonPanelLayout.setVerticalGroup( + buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(saveButton) + .addComponent(backButton)); + + + // GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + // buttonPanel.setLayout(buttonPanelLayout); + // + // buttonPanelLayout.setHorizontalGroup( + // buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(GroupLayout.Alignment.TRAILING, buttonPanelLayout.createSequentialGroup().addContainerGap(15, Short.MAX_VALUE).addComponent(saveButton).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(cancelButton).addContainerGap())); + // buttonPanelLayout.setVerticalGroup( + // buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(saveButton).addComponent(cancelButton))); + + contentPanel.validate(); + } + }); + } - JLabel refIdLabel = new JLabel(); - refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - String refIdLabelPattern = messages.getString(MESSAGE_HASHDATA); - refIdLabel.setText(MessageFormat.format(refIdLabelPattern, new Object[]{refId})); + private void showMultipleHashDataInputDialog(final TableModel signedReferences, final ActionListener cancelListener, final String cancelCommand, final ActionListener saveListener, final String saveCommand) { + SwingUtilities.invokeLater(new Runnable() { - JScrollPane hashDataScrollPane = new JScrollPane(); - JTextArea hashDataTextArea = new JTextArea(text); - hashDataTextArea.setEditable(false); - hashDataTextArea.setColumns(1); - hashDataTextArea.setRows(1); - hashDataScrollPane.setViewportView(hashDataTextArea); + @Override + public void run() { + mainPanel.removeAll(); + buttonPanel.removeAll(); - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); + titleLabel.setText(messages.getString(TITLE_HASHDATA)); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(refIdLabel) - .addComponent(hashDataScrollPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap()); + JLabel refIdLabel = new JLabel(); + refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + String refIdLabelPattern = messages.getString(MESSAGE_HASHDATALIST); + refIdLabel.setText(MessageFormat.format(refIdLabelPattern, new Object[]{signedReferences.getRowCount()})); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(refIdLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(hashDataScrollPane, 0, GroupLayout.PREFERRED_SIZE, hashDataTextArea.getPreferredSize().height+3)); + JTable hashDataTable = new JTable(); + hashDataTable.setModel(signedReferences); + hashDataTable.setTableHeader(null); + // hashDataTable.setShowVerticalLines(false); + // hashDataTable.setRowSelectionAllowed(false); + TableColumn selectCol = hashDataTable.getColumnModel().getColumn(1); + selectCol.setMinWidth(CHECKBOX_WIDTH); + selectCol.setMaxWidth(CHECKBOX_WIDTH); + + + hashDataTable.setPreferredScrollableViewportSize(mainPanel.getPreferredSize()); - - -// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); -// mainPanel.setLayout(mainPanelLayout); -// -// mainPanelLayout.setHorizontalGroup( -// mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(mainPanelLayout.createSequentialGroup().addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(refIdLabel).addComponent(hashDataScrollPane, GroupLayout.PREFERRED_SIZE, PREF_SIZE_PINFIELD, Short.MAX_VALUE)).addContainerGap())); -// -// mainPanelLayout.setVerticalGroup( -// mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(mainPanelLayout.createSequentialGroup().addComponent(refIdLabel).addGap(refIdLabel.getFont().getSize()).addComponent(hashDataScrollPane).addGap(refIdLabel.getFont().getSize()))); + JScrollPane hashDataScrollPane = new JScrollPane(hashDataTable); - backButton.setActionCommand(cancelCommand); - backButton.addActionListener(cancelListener); + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); - saveButton.setActionCommand(saveCommand); - saveButton.addActionListener(saveListener); - - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - -// buttonPanelLayout.linkSize(cancelButton, okButton, signButton, backButton, saveButton); - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) - .addContainerGap()); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(saveButton) - .addComponent(backButton)); - - -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// buttonPanelLayout.setHorizontalGroup( -// buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(GroupLayout.Alignment.TRAILING, buttonPanelLayout.createSequentialGroup().addContainerGap(15, Short.MAX_VALUE).addComponent(saveButton).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(cancelButton).addContainerGap())); -// buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(saveButton).addComponent(cancelButton))); + mainPanelLayout.setHorizontalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(refIdLabel) + .addComponent(hashDataScrollPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()); - contentPanel.validate(); - } + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addComponent(refIdLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(hashDataScrollPane, 0, GroupLayout.PREFERRED_SIZE, hashDataTable.getPreferredSize().height+3)); + // .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)); - private void showMultipleHashDataInputDialog(final TableModel signedReferences, final ActionListener cancelListener, final String cancelCommand, ActionListener saveListener, String saveCommand) { - mainPanel.removeAll(); - buttonPanel.removeAll(); - - titleLabel.setText(messages.getString(TITLE_HASHDATA)); - - JLabel refIdLabel = new JLabel(); - refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - String refIdLabelPattern = messages.getString(MESSAGE_HASHDATALIST); - refIdLabel.setText(MessageFormat.format(refIdLabelPattern, new Object[]{signedReferences.getRowCount()})); - - JTable hashDataTable = new JTable(); - hashDataTable.setModel(signedReferences); - hashDataTable.setTableHeader(null); -// hashDataTable.setShowVerticalLines(false); -// hashDataTable.setRowSelectionAllowed(false); - TableColumn selectCol = hashDataTable.getColumnModel().getColumn(1); - selectCol.setMinWidth(CHECKBOX_WIDTH); - selectCol.setMaxWidth(CHECKBOX_WIDTH); - - - hashDataTable.setPreferredScrollableViewportSize(mainPanel.getPreferredSize()); - - JScrollPane hashDataScrollPane = new JScrollPane(hashDataTable); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(refIdLabel) - .addComponent(hashDataScrollPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap()); - - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(refIdLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(hashDataScrollPane, 0, GroupLayout.PREFERRED_SIZE, hashDataTable.getPreferredSize().height+3)); -// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)); - - -// -// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); -// mainPanel.setLayout(mainPanelLayout); -// -// mainPanelLayout.setHorizontalGroup( -// mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addGroup(mainPanelLayout.createSequentialGroup() -// .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addComponent(refIdLabel) -// .addComponent(hashDataScrollPane, GroupLayout.PREFERRED_SIZE, PREF_SIZE_PINFIELD, Short.MAX_VALUE)) -// .addContainerGap())); -// -// mainPanelLayout.setVerticalGroup( -// mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addGroup(mainPanelLayout.createSequentialGroup() -// .addComponent(refIdLabel) -// .addGap(refIdLabel.getFont().getSize()) -// .addComponent(hashDataScrollPane) -// .addGap(refIdLabel.getFont().getSize()))); - - - - - - - - - - - -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// buttonPanelLayout.setHorizontalGroup( -// buttonPanelLayout.createSequentialGroup() -//// buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -//// .addGroup(GroupLayout.Alignment.TRAILING, buttonPanelLayout.createSequentialGroup() -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(saveButton) -// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) -// .addComponent(cancelButton) -// .addContainerGap()); //); -// buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addGroup(GroupLayout.Alignment.TRAILING, buttonPanelLayout.createSequentialGroup() -// .addGroup(buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) -// .addComponent(saveButton) -// .addComponent(cancelButton)) -// .addContainerGap())); + // + // GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + // mainPanel.setLayout(mainPanelLayout); + // + // mainPanelLayout.setHorizontalGroup( + // mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + // .addGroup(mainPanelLayout.createSequentialGroup() + // .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + // .addComponent(refIdLabel) + // .addComponent(hashDataScrollPane, GroupLayout.PREFERRED_SIZE, PREF_SIZE_PINFIELD, Short.MAX_VALUE)) + // .addContainerGap())); + // + // mainPanelLayout.setVerticalGroup( + // mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + // .addGroup(mainPanelLayout.createSequentialGroup() + // .addComponent(refIdLabel) + // .addGap(refIdLabel.getFont().getSize()) + // .addComponent(hashDataScrollPane) + // .addGap(refIdLabel.getFont().getSize()))); - - backButton.setActionCommand(cancelCommand); - backButton.addActionListener(cancelListener); - saveButton.setActionCommand(saveCommand); - saveButton.addActionListener(saveListener); - - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - -// buttonPanelLayout.linkSize(cancelButton, okButton, signButton, backButton, saveButton); - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) - .addContainerGap());//); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(saveButton) - .addComponent(backButton)); - - contentPanel.validate(); + + + + + + + + + + + // GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + // buttonPanel.setLayout(buttonPanelLayout); + // + // buttonPanelLayout.setHorizontalGroup( + // buttonPanelLayout.createSequentialGroup() + //// buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + //// .addGroup(GroupLayout.Alignment.TRAILING, buttonPanelLayout.createSequentialGroup() + // .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + // .addComponent(saveButton) + // .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + // .addComponent(cancelButton) + // .addContainerGap()); //); + // buttonPanelLayout.setVerticalGroup( + // buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + // .addGroup(GroupLayout.Alignment.TRAILING, buttonPanelLayout.createSequentialGroup() + // .addGroup(buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + // .addComponent(saveButton) + // .addComponent(cancelButton)) + // .addContainerGap())); + + + JButton backButton = new JButton(); + backButton.setText(messages.getString(BUTTON_BACK)); + backButton.setActionCommand(cancelCommand); + backButton.addActionListener(cancelListener); + + JButton saveButton = new JButton(); + saveButton.setText(messages.getString(BUTTON_SAVE)); + saveButton.setActionCommand(saveCommand); + saveButton.addActionListener(saveListener); + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + // buttonPanelLayout.linkSize(cancelButton, okButton, signButton, backButton, saveButton); + buttonPanelLayout.setHorizontalGroup( + buttonPanelLayout.createSequentialGroup() + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addContainerGap());//); + buttonPanelLayout.setVerticalGroup( + buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(saveButton) + .addComponent(backButton)); + + contentPanel.validate(); + } + }); } - private void showSaveHashDataInputDialog(HashDataInput signedRef, ActionListener okListener, String okCommand) { - String dir = System.getProperty("user.home"); - JFileChooser fileDialog = new JFileChooser(dir); - fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileDialog.setMultiSelectionEnabled(false); - fileDialog.setDialogTitle(messages.getString(WINDOWTITLE_SAVE)); - fileDialog.setDialogType(JFileChooser.SAVE_DIALOG); - fileDialog.setFileHidingEnabled(true); - MimeFilter mimeFilter = new MimeFilter(signedRef.getMimeType()); - fileDialog.setFileFilter(mimeFilter); - String filename = messages.getString(SAVE_HASHDATAINPUT_PREFIX) + mimeFilter.getExtension(); - fileDialog.setSelectedFile(new File(dir, filename)); - switch (fileDialog.showSaveDialog(contentPane)) { +// private DisposableFileChooser fileDialog; + + private void showSaveHashDataInputDialog(final List signedRefs, final ActionListener okListener, final String okCommand) { + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + String userHome = System.getProperty("user.home"); + + JFileChooser fileDialog = new JFileChooser(userHome); + fileDialog.setMultiSelectionEnabled(false); + fileDialog.setDialogType(JFileChooser.SAVE_DIALOG); + fileDialog.setFileHidingEnabled(true); + if (signedRefs.size() == 1) { + fileDialog.setDialogTitle(messages.getString(WINDOWTITLE_SAVE)); + fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); + String mimeType = signedRefs.get(0).getMimeType(); + MimeFilter mimeFilter = new MimeFilter(mimeType, messages); + fileDialog.setFileFilter(mimeFilter); + String filename = messages.getString(SAVE_HASHDATAINPUT_PREFIX) + MimeFilter.getExtension(mimeType); + fileDialog.setSelectedFile(new File(userHome, filename)); + } else { + fileDialog.setDialogTitle(messages.getString(WINDOWTITLE_SAVEDIR)); + fileDialog.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + } + + //parent contentPane -> placed over applet + switch (fileDialog.showSaveDialog(fileDialog)) { case JFileChooser.APPROVE_OPTION: - File f = fileDialog.getSelectedFile(); - if (f.exists()) { -// log.debug("hashDataInput file exists, overwrite?"); - String ovrwrt = messages.getString(MESSAGE_OVERWRITE); - int overwrite = JOptionPane.showConfirmDialog(contentPane, MessageFormat.format(ovrwrt, filename), messages.getString(WINDOWTITLE_OVERWRITE), JOptionPane.OK_CANCEL_OPTION); - if (overwrite != JOptionPane.OK_OPTION) { -// log.debug("User canceled overwrite HashDataInput, returning to SignaturePin dialog"); - okListener.actionPerformed(new ActionEvent(fileDialog, ActionEvent.ACTION_PERFORMED, okCommand)); - return; - } + File f = fileDialog.getSelectedFile(); + for (HashDataInput hashDataInput : signedRefs) { + String mimeType = hashDataInput.getMimeType(); + String id = hashDataInput.getReferenceId(); + File file; + if (f.isDirectory()) { + String filename = messages.getString(SAVE_HASHDATAINPUT_PREFIX) + '_' + id + MimeFilter.getExtension(mimeType); + file = new File(f, filename); + } else { + file = f; + } + if (file.exists()) { + String ovrwrt = messages.getString(MESSAGE_OVERWRITE); + int overwrite = JOptionPane.showConfirmDialog(fileDialog, MessageFormat.format(ovrwrt, file), messages.getString(WINDOWTITLE_OVERWRITE), JOptionPane.OK_CANCEL_OPTION); + if (overwrite != JOptionPane.OK_OPTION) { + continue; + } } if (log.isDebugEnabled()) { - log.debug("Writing HashDataInput " + signedRef.getReferenceId() + " (" + signedRef.getMimeType() + ") to file " + f); + log.debug("Writing HashDataInput " + id + " (" + mimeType + ") to file " + file); } FileOutputStream fos = null; try { - fos = new FileOutputStream(f); + fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos); - InputStream hdi = signedRef.getHashDataInput(); + InputStream hdi = hashDataInput.getHashDataInput(); int b; while ((b = hdi.read()) != -1) { bos.write(b); @@ -1134,7 +1200,7 @@ public class BKUGUI implements BKUGUIFacade { bos.flush(); bos.close(); } catch (IOException ex) { - log.error("Failed to write HashDataInput to file " + f + ": " + ex.getMessage()); + log.error("Failed to write HashDataInput to file " + file + ": " + ex.getMessage()); showErrorDialog("Failed to write signed reference to file: " + ex.getMessage(), null, null); ex.printStackTrace(); } finally { @@ -1142,11 +1208,15 @@ public class BKUGUI implements BKUGUIFacade { fos.close(); } catch (IOException ex) { } - } + } + } + } + log.debug("done saving hashdatainput"); + okListener.actionPerformed(new ActionEvent(fileDialog, ActionEvent.ACTION_PERFORMED, okCommand)); } - okListener.actionPerformed(new ActionEvent(fileDialog, ActionEvent.ACTION_PERFORMED, okCommand)); + }); } - + @Override public void showWaitDialog(final String waitMessage) { SwingUtilities.invokeLater(new Runnable() { @@ -1190,149 +1260,4 @@ public class BKUGUI implements BKUGUIFacade { return null; } - class PINDocument extends PlainDocument { - - private PINSpec pinSpec; - private Pattern pinPattern; - private JButton enterButton; - - public PINDocument(PINSpec pinSpec, JButton enterButton) { - this.pinSpec = pinSpec; - if (pinSpec.getRexepPattern() != null) { - pinPattern = Pattern.compile(pinSpec.getRexepPattern()); - } else { - pinPattern = Pattern.compile("."); - } - this.enterButton = enterButton; - } - - @Override - public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { - if (pinSpec.getMaxLength() >= (getLength() + str.length())) { - boolean matches = true; - for (int i = 0; i < str.length(); i++) { - Matcher m = pinPattern.matcher(str.substring(i, i + 1)); - if (!m.matches()) { - matches = false; - } - } - if (matches) { - super.insertString(offs, str, a); - } - } - enterButton.setEnabled(getLength() >= pinSpec.getMinLength()); - } - - @Override - public void remove(int offs, int len) throws BadLocationException { - super.remove(offs, len); - enterButton.setEnabled(getLength() >= pinSpec.getMinLength()); - } - } - - class MimeFilter extends FileFilter { - - protected String mimeType; - - public MimeFilter(String mimeType) { - this.mimeType = mimeType; - } - - @Override - public boolean accept(File f) { - - if (f.isDirectory()) { - return true; - } - - String ext = getExtension(f); - if ("text/xml".equals(mimeType)) { - return "xml".equalsIgnoreCase(ext); - } else if ("text/html".equals(mimeType)) { - return "html".equalsIgnoreCase(ext) || "htm".equalsIgnoreCase(ext); - } else if ("application/xhtml+xml".equals(mimeType)) { - return "xhtml".equalsIgnoreCase(ext); - } else if ("text/plain".equals(mimeType)) { - return "txt".equalsIgnoreCase(ext); - } else if ("application/pdf".equals(mimeType)) { - return "pdf".equalsIgnoreCase(ext); - } else { - return true; - } - } - - private String getExtension(File f) { - String ext = null; - String s = f.getName(); - int i = s.lastIndexOf('.'); - - if (i > 0 && i < s.length() - 1) { - ext = s.substring(i + 1).toLowerCase(); - } - return ext; - } - - @Override - public String getDescription() { - if ("text/xml".equals(mimeType)) { - return messages.getString(MIMETYPE_DESC_XML); - } else if ("text/html".equals(mimeType)) { - return messages.getString(MIMETYPE_DESC_HTML); - } else if ("application/xhtml+xml".equals(mimeType)) { - return messages.getString(MIMETYPE_DESC_XHTML); - } else if ("text/plain".equals(mimeType)) { - return messages.getString(MIMETYPE_DESC_TXT); - } else if ("application/pdf".equals(mimeType)) { - return messages.getString(MIMETYPE_DESC_PDF); - } else { - return messages.getString(MIMETYPE_DESC_BIN); - } - } - - public String getExtension() { - if ("text/xml".equals(mimeType)) { - return ".xml"; - } else if ("text/html".equals(mimeType)) { - return ".html"; - } else if ("application/xhtml+xml".equals(mimeType)) { - return ".xhtml"; - } else if ("text/plain".equals(mimeType)) { - return ".txt"; - } else if ("application/pdf".equals(mimeType)) { - return ".pdf"; - } else { - return ".bin"; - } - } - } - - class HashDataTableModel extends DefaultTableModel { - - Class[] types = new Class[]{ - java.lang.String.class, java.lang.Boolean.class - }; - - public HashDataTableModel(List signedReferences) { - super(0, 2); - for (HashDataInput hashDataInput : signedReferences) { - addRow(new Object[]{hashDataInput.getReferenceId(), new Boolean(true)}); - } - } - - @Override - public Class getColumnClass(int columnIndex) { - return types [columnIndex]; - } - - public List getSelectedReferenceIds() { - ArrayList selection = new ArrayList(); - for (Object row : dataVector) { - if ((Boolean) ((Vector) row).elementAt(1)) { - selection.add((String) ((Vector) row).elementAt(0)); - } - } - return selection; - } - - } } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index f8b80556..f4b6325d 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -53,6 +53,8 @@ public interface BKUGUIFacade { public void showHashDataInputDialog(List signedReferences, ActionListener okListener, String actionCommand); +// public void showPlainTextHashDataInputDialog(String text, ActionListener saveListener, String saveCommand, ActionListener cancelListener, String cancelCommand); + public void showErrorDialog(String errorMsg, ActionListener okListener, String actionCommand); public void showErrorDialog(String errorMsg); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java new file mode 100644 index 00000000..061a2849 --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java @@ -0,0 +1,71 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.gui; + +import at.gv.egiz.stal.HashDataInput; +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; +import javax.swing.table.DefaultTableModel; + +/** + * + * @author clemens + */ +class HashDataTableModel extends DefaultTableModel { + + protected List signedReferences; + + Class[] types = new Class[]{ + java.lang.String.class, java.lang.Boolean.class + }; + + public HashDataTableModel(List signedReferences) { + super(0, 2); + this.signedReferences = signedReferences; + for (HashDataInput hashDataInput : signedReferences) { + String desc = hashDataInput.getReferenceId() + " (" + hashDataInput.getMimeType() + ")"; + addRow(new Object[]{desc, new Boolean(true)}); + } + } + + @Override + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public List getSelectedHashData() { + ArrayList selection = new ArrayList(); + for (int i = 0; i < dataVector.size(); i++) { + if ((Boolean) ((Vector) dataVector.get(i)).elementAt(1)) { + selection.add(signedReferences.get(i)); + } + } + return selection; + } + +// public List getSelectedReferenceIds() { +// ArrayList selection = new ArrayList(); +// for (Object row : dataVector) { +// if ((Boolean) ((Vector) row).elementAt(1)) { +// selection.add((String) ((Vector) row).elementAt(0)); +// } +// } +// return selection; +// } + + } \ No newline at end of file diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/MimeFilter.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/MimeFilter.java new file mode 100644 index 00000000..6ee61a82 --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/MimeFilter.java @@ -0,0 +1,98 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package at.gv.egiz.bku.gui; + +import java.io.File; +import java.util.ResourceBundle; +import javax.swing.filechooser.FileFilter; + +/** + * + * @author clemens + */ +class MimeFilter extends FileFilter { + + private static final String MIMETYPE_DESC_XML = "mimetype.desc.xml"; + private static final String MIMETYPE_DESC_HTML = "mimetype.desc.html"; + private static final String MIMETYPE_DESC_XHTML = "mimetype.desc.xhtml"; + private static final String MIMETYPE_DESC_TXT = "mimetype.desc.txt"; + private static final String MIMETYPE_DESC_PDF = "mimetype.desc.pdf"; + private static final String MIMETYPE_DESC_BIN = "mimetype.desc.bin"; + + protected String mimeType; + protected ResourceBundle messages; + + public MimeFilter(String mimeType, ResourceBundle messages) { + this.mimeType = mimeType; + this.messages = messages; + } + + @Override + public boolean accept(File f) { + + if (f.isDirectory()) { + return true; + } + + String ext = getExtension(f); + if ("text/xml".equals(mimeType)) { + return "xml".equalsIgnoreCase(ext); + } else if ("text/html".equals(mimeType)) { + return "html".equalsIgnoreCase(ext) || "htm".equalsIgnoreCase(ext); + } else if ("application/xhtml+xml".equals(mimeType)) { + return "xhtml".equalsIgnoreCase(ext); + } else if ("text/plain".equals(mimeType)) { + return "txt".equalsIgnoreCase(ext); + } else if ("application/pdf".equals(mimeType)) { + return "pdf".equalsIgnoreCase(ext); + } else { + return true; + } + } + + private String getExtension(File f) { + String ext = null; + String s = f.getName(); + int i = s.lastIndexOf('.'); + + if (i > 0 && i < s.length() - 1) { + ext = s.substring(i + 1).toLowerCase(); + } + return ext; + } + + @Override + public String getDescription() { + if ("text/xml".equals(mimeType)) { + return messages.getString(MIMETYPE_DESC_XML); + } else if ("text/html".equals(mimeType)) { + return messages.getString(MIMETYPE_DESC_HTML); + } else if ("application/xhtml+xml".equals(mimeType)) { + return messages.getString(MIMETYPE_DESC_XHTML); + } else if ("text/plain".equals(mimeType)) { + return messages.getString(MIMETYPE_DESC_TXT); + } else if ("application/pdf".equals(mimeType)) { + return messages.getString(MIMETYPE_DESC_PDF); + } else { + return messages.getString(MIMETYPE_DESC_BIN); + } + } + + public static String getExtension(String mimeType) { + if ("text/xml".equals(mimeType)) { + return ".xml"; + } else if ("text/html".equals(mimeType)) { + return ".html"; + } else if ("application/xhtml+xml".equals(mimeType)) { + return ".xhtml"; + } else if ("text/plain".equals(mimeType)) { + return ".txt"; + } else if ("application/pdf".equals(mimeType)) { + return ".pdf"; + } else { + return ".bin"; + } + } +} \ No newline at end of file diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java new file mode 100644 index 00000000..e8572742 --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java @@ -0,0 +1,58 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package at.gv.egiz.bku.gui; + +import at.gv.egiz.smcc.PINSpec; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JButton; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; + +/** + * + * @author clemens + */ +class PINDocument extends PlainDocument { + + private PINSpec pinSpec; + private Pattern pinPattern; + private JButton enterButton; + + public PINDocument(PINSpec pinSpec, JButton enterButton) { + this.pinSpec = pinSpec; + if (pinSpec.getRexepPattern() != null) { + pinPattern = Pattern.compile(pinSpec.getRexepPattern()); + } else { + pinPattern = Pattern.compile("."); + } + this.enterButton = enterButton; + } + + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + if (pinSpec.getMaxLength() >= (getLength() + str.length())) { + boolean matches = true; + for (int i = 0; i < str.length(); i++) { + Matcher m = pinPattern.matcher(str.substring(i, i + 1)); + if (!m.matches()) { + matches = false; + } + } + if (matches) { + super.insertString(offs, str, a); + } + } + enterButton.setEnabled(getLength() >= pinSpec.getMinLength()); + } + + @Override + public void remove(int offs, int len) throws BadLocationException { + super.remove(offs, len); + enterButton.setEnabled(getLength() >= pinSpec.getMinLength()); + } + } \ No newline at end of file diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index b651fa8d..a329ba86 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -23,6 +23,7 @@ title.retry=Falscher PIN title.wait=Bitte warten title.hashdata=Signaturdaten windowtitle.save=Signaturdaten speichern +windowtitle.savedir=Signaturdaten in Verzeichnis speichern windowtitle.overwrite=Datei \u00FCberschreiben? message.wait=Bitte warten... message.insertcard=Bitte B\u00FCrgerkarte in den Kartenleser stecken @@ -34,16 +35,16 @@ message.retries=Noch {0} Versuche message.overwrite=M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben? label.pin={0}: label.pinsize=({0} stellig) -error.hashdata=Keine Signaturdaten verf\u00FCgbar +error.no.hashdata=Keine Signaturdaten verf\u00FCgbar button.ok=OK button.cancel=Abbrechen button.back=Zur\u00FCck button.sign=Signieren button.save=Speichern... -mimetype.desc.xml=XML-Dateien (*.xml) -mimetype.desc.html=HTML-Dateien (*.html, *.htm) -mimetype.desc.xhtml=XHTML-Dateien (*.xhtml) -mimetype.desc.txt=Textdateien (*.txt) -mimetype.desc.pdf=Adobe PDF-Dateien (*.pdf) -mimetype.desc.bin=Bin\u00E4rdateien (*.bin) +mimetype.desc.xml=XML-Dateien (.xml) +mimetype.desc.html=HTML-Dateien (.html, .htm) +mimetype.desc.xhtml=XHTML-Dateien (.xhtml) +mimetype.desc.txt=Textdateien (.txt) +mimetype.desc.pdf=Adobe PDF-Dateien (.pdf) +mimetype.desc.bin=Bin\u00E4rdateien (.bin) save.hashdatainput.prefix=Signaturdaten diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index 4367f642..85f05435 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -1,19 +1,19 @@ /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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. -*/ + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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. + */ /* * To change this template, choose Tools | Templates * and open the template in the editor. @@ -35,137 +35,137 @@ import java.util.List; */ public class BKUGUIWorker implements Runnable { - BKUGUIFacade gui; + BKUGUIFacade gui; - public void init(BKUGUIFacade gui) { - this.gui = gui; - } + public void init(BKUGUIFacade gui) { + this.gui = gui; + } - @Override - public void run() { + @Override + public void run() { // try { - final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN"); - - - final ActionListener cancelListener = new ActionListener() { - - public void actionPerformed(ActionEvent e) { - System.out.println("CANCEL EVENT OCCURED: " + e); - } - }; - ActionListener okListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - System.out.println("OK EVENT OCCURED: " + e); - } - }; - final ActionListener signListener = new ActionListener() { - - public void actionPerformed(ActionEvent e) { - System.out.println("SIGN EVENT OCCURED: " + e); - } - }; - ActionListener hashdataListener = new ActionListener() { - - public void actionPerformed(ActionEvent e) { - System.out.println("HASHDATA EVENT OCCURED: " + e); - ActionListener returnListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", null, "hashdata"); - } - }; - HashDataInput signedRef1 = new HashDataInput() { - - @Override - public InputStream getHashDataInput() { - return new ByteArrayInputStream("HashDataInput_001\n12345\n\tHello, world!\n12345\n\n12345\n6789\nblabla".getBytes()); - } - - @Override - public String getMimeType() { - return "text/plain"; - } - - @Override - public String getReferenceId() { - return "Reference-ref1-00000000000000000000001"; - } - }; - HashDataInput signedRef2 = new HashDataInput() { - - @Override - public InputStream getHashDataInput() { - return new ByteArrayInputStream("HashDataInput_002".getBytes()); - } - - @Override - public String getMimeType() { - return "text/xml"; - } - - @Override - public String getReferenceId() { - return "Reference-ref2-00000000000000000000002"; - } - }; - HashDataInput signedRef3 = new HashDataInput() { - - @Override - public InputStream getHashDataInput() { - return new ByteArrayInputStream("HashDataInput_003".getBytes()); - } - - @Override - public String getMimeType() { - return "text/xml"; - } - - @Override - public String getReferenceId() { - return "Reference-ref3-00000000000000000000003"; - } - }; - HashDataInput signedRef4 = new HashDataInput() { - - @Override - public InputStream getHashDataInput() { - return new ByteArrayInputStream("HashDataInput_004".getBytes()); - } - - @Override - public String getMimeType() { - return "text/xml"; - } - - @Override - public String getReferenceId() { - return "ref4"; - } - }; - - // - List signedRefs = new ArrayList(); - signedRefs.add(signedRef1); + final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN"); + + + final ActionListener cancelListener = new ActionListener() { + + public void actionPerformed(ActionEvent e) { + System.out.println("CANCEL EVENT OCCURED: " + e); + } + }; + ActionListener okListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("OK EVENT OCCURED: " + e); + } + }; + final ActionListener signListener = new ActionListener() { + + public void actionPerformed(ActionEvent e) { + System.out.println("SIGN EVENT OCCURED: " + e); + } + }; + ActionListener hashdataListener = new ActionListener() { + + public void actionPerformed(ActionEvent e) { + System.out.println("HASHDATA EVENT OCCURED: " + e); + ActionListener returnListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", null, "hashdata"); + } + }; + HashDataInput signedRef1 = new HashDataInput() { + + @Override + public InputStream getHashDataInput() { + return new ByteArrayInputStream("oialfx HashDataInput_001\n12345\n\tHello, world!\n12345\n\n12345\n6789\nblabla".getBytes()); + } + + @Override + public String getMimeType() { + return "text/plain"; + } + + @Override + public String getReferenceId() { + return "Reference-ref1-00000000000000000000001"; + } + }; + HashDataInput signedRef2 = new HashDataInput() { + + @Override + public InputStream getHashDataInput() { + return new ByteArrayInputStream("HashDataInput_002".getBytes()); + } + + @Override + public String getMimeType() { + return "text/xml"; + } + + @Override + public String getReferenceId() { + return "Reference-ref2-00000000000000000000002"; + } + }; + HashDataInput signedRef3 = new HashDataInput() { + + @Override + public InputStream getHashDataInput() { + return new ByteArrayInputStream("HashDataInput_003".getBytes()); + } + + @Override + public String getMimeType() { + return "text/xml"; + } + + @Override + public String getReferenceId() { + return "Reference-ref3-00000000000000000000003"; + } + }; + HashDataInput signedRef4 = new HashDataInput() { + + @Override + public InputStream getHashDataInput() { + return new ByteArrayInputStream("HashDataInput_004".getBytes()); + } + + @Override + public String getMimeType() { + return "text/xml"; + } + + @Override + public String getReferenceId() { + return "ref4"; + } + }; + + // + List signedRefs = new ArrayList(); + signedRefs.add(signedRef1); signedRefs.add(signedRef2); signedRefs.add(signedRef3); signedRefs.add(signedRef4); // signedRefs = Collections.singletonList(signedRef1); - gui.showHashDataInputDialog(signedRefs, returnListener, "return"); - } - }; - + gui.showHashDataInputDialog(signedRefs, returnListener, "return"); + } + }; + // gui.showWelcomeDialog(); // // Thread.sleep(2000); - + // gui.showInsertCardDialog(cancelListener, "cancel"); - + // Thread.sleep(2000); // // gui.showCardNotSupportedDialog(cancelListener, "cancel"); @@ -178,11 +178,11 @@ public class BKUGUIWorker implements Runnable { // // Thread.sleep(2000); // - - gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); + + gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); // Thread.sleep(2000); - + // gui.showSignaturePINRetryDialog(signPinSpec, 2, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); // // Thread.sleep(2000); @@ -192,13 +192,13 @@ public class BKUGUIWorker implements Runnable { // Thread.sleep(2000); // // gui.showErrorDialog("Testfehler occured"); - - + + // gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save"); // Thread.sleep(2000); // } catch (InterruptedException ex) { // ex.printStackTrace(); // } - } + } } diff --git a/BKUOnline/pom.xml b/BKUOnline/pom.xml index d31367a8..a50954cd 100644 --- a/BKUOnline/pom.xml +++ b/BKUOnline/pom.xml @@ -58,11 +58,13 @@ 1.0-SNAPSHOT compile - + + + at.gv.egiz + BKUApplet + 1.0-SNAPSHOT + provided + @@ -177,4 +179,5 @@ +>>>>>>> .r33 diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 1f84300a..d37d0551 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -47,6 +47,8 @@ import at.gv.egiz.stal.signedinfo.ObjectFactory; import at.gv.egiz.stal.signedinfo.ReferenceType; import at.gv.egiz.stal.signedinfo.SignedInfoType; import at.gv.egiz.stal.util.JCEAlgorithmNames; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -150,9 +152,6 @@ public class SignRequestHandler extends AbstractRequestHandler implements hashDataInputs = getHashDataInputs(signedInfo.getReference()); } gui.showHashDataInputDialog(hashDataInputs, this, "ok"); - waitForAction(); - gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, - "hashData"); } catch (Exception ex) { //FIXME localize messages log.error("Failed to obtain HashDataInputs: " + ex.getMessage()); @@ -178,6 +177,7 @@ public class SignRequestHandler extends AbstractRequestHandler implements /** * override by subclass + * @post-condition returned list != null * @return */ protected List getHashDataInputs(List signedReferences) throws Exception { -- cgit v1.2.3 From cf82096145bbdd548e388c1bc25f0e703b9b4624 Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 17 Sep 2008 17:17:10 +0000 Subject: hashdatainput digest verification git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@44 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../bku/online/applet/WSSignRequestHandler.java | 139 +++++++---- .../gv/egiz/stal/impl/ByteArrayHashDataInput.java | 58 +++++ .../bku/local/stal/LocalSignRequestHandler.java | 14 +- .../gv/egiz/stal/impl/ByteArrayHashDataInput.java | 58 ----- .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 2 +- .../bku/smccstal/CashedHashDataInputResolver.java | 27 ++ .../gv/egiz/bku/smccstal/SignRequestHandler.java | 273 ++++++++++++++++----- 7 files changed, 404 insertions(+), 167 deletions(-) create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java delete mode 100644 STALService/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/CashedHashDataInputResolver.java (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java index 5186de1a..6dae264c 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java @@ -16,15 +16,20 @@ */ package at.gv.egiz.bku.online.applet; -import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; import at.gv.egiz.bku.smccstal.SignRequestHandler; +import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.impl.ByteArrayHashDataInput; import at.gv.egiz.stal.service.GetHashDataInputResponseType; import at.gv.egiz.stal.service.GetHashDataInputType; import at.gv.egiz.stal.service.STALPortType; +import at.gv.egiz.stal.signedinfo.DigestMethodType; import at.gv.egiz.stal.signedinfo.ReferenceType; +import java.security.DigestException; +import java.security.MessageDigest; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -35,57 +40,101 @@ import org.apache.commons.logging.LogFactory; */ public class WSSignRequestHandler extends SignRequestHandler { - private static final Log log = LogFactory.getLog(WSSignRequestHandler.class); - STALPortType stalPort; - String sessId; + private static final Log log = LogFactory.getLog(WSSignRequestHandler.class); + STALPortType stalPort; + String sessId; - public WSSignRequestHandler(String sessId, STALPortType stalPort) { - if (stalPort == null || sessId == null) { - throw new NullPointerException("STAL port must not be null"); - } - this.sessId = sessId; - this.stalPort = stalPort; + public WSSignRequestHandler(String sessId, STALPortType stalPort) { + if (stalPort == null || sessId == null) { + throw new NullPointerException("STAL port must not be null"); } + this.sessId = sessId; + this.stalPort = stalPort; + } - @Override - protected List getHashDataInputs(List dsigReferences) throws Exception { - GetHashDataInputType request = new GetHashDataInputType(); - request.setSessionId(sessId); - for (ReferenceType dsigRef : dsigReferences) { - //don't get Manifest, QualifyingProperties, ... - if (dsigRef.getType() == null) { - String dsigRefId = dsigRef.getId(); - if (dsigRefId != null) { - GetHashDataInputType.Reference reference = new GetHashDataInputType.Reference(); - reference.setID(dsigRefId); - request.getReference().add(reference); - } else { - throw new Exception("Cannot get HashDataInput for dsig:Reference without Id attribute"); - } - } - } + @Override + public List getCashedHashDataInputs(List signedReferences) throws Exception { - if (log.isDebugEnabled()) { - log.debug("Calling GetHashDataInput for session " + sessId); - } - GetHashDataInputResponseType response = stalPort.getHashDataInput(request); - ArrayList hashDataInputs = new ArrayList(); - for (GetHashDataInputResponseType.Reference reference : response.getReference()) { - byte[] hdi = reference.getValue(); - String id = reference.getID(); - String mimeType = reference.getMimeType(); - String encoding = reference.getEncoding(); + GetHashDataInputType request = new GetHashDataInputType(); + request.setSessionId(sessId); + + HashMap idRefMap = new HashMap(); + for (ReferenceType reference : signedReferences) { + //don't get Manifest, QualifyingProperties, ... + if (reference.getType() == null) { + String referenceId = reference.getId(); + if (referenceId != null) { + idRefMap.put(referenceId, reference); + GetHashDataInputType.Reference ref = new GetHashDataInputType.Reference(); + ref.setID(referenceId); + request.getReference().add(ref); - if (log.isDebugEnabled()) { - log.debug("Got HashDataInput " + id + " (" + mimeType + ";" + encoding + ")"); - } - hashDataInputs.add(new ByteArrayHashDataInput(hdi, id, mimeType, encoding)); + } else { + throw new Exception("Cannot resolve HashDataInput for reference without Id attribute"); } - return hashDataInputs; + } } - @Override - public SMCCSTALRequestHandler newInstance() { - return new WSSignRequestHandler(this.sessId, this.stalPort); + if (log.isDebugEnabled()) { + log.debug("Calling GetHashDataInput for session " + sessId); } + GetHashDataInputResponseType response = stalPort.getHashDataInput(request); + ArrayList hashDataInputs = new ArrayList(); + + for (GetHashDataInputResponseType.Reference reference : response.getReference()) { + + String id = reference.getID(); + byte[] hdi = reference.getValue(); + if (hdi == null) { + throw new Exception("Failed to resolve digest value for reference " + id); + } + String mimeType = reference.getMimeType(); + String encoding = reference.getEncoding(); + + if (log.isDebugEnabled()) { + log.debug("Got HashDataInput " + id + " (" + mimeType + ";" + encoding + ")"); + } + + ReferenceType dsigRef = idRefMap.get(id); + DigestMethodType dm = dsigRef.getDigestMethod(); + if (dm == null) { + throw new Exception("Failed to verify digest value for reference " + id + ": no digest algorithm"); + } + //TODO + String mdAlg = dm.getAlgorithm(); + if ("http://www.w3.org/2000/09/xmldsig#sha1".equals(mdAlg)) + mdAlg = "SHA-1"; + else if ("http://www.w3.org/2001/04/xmlenc#sha256".equals(mdAlg)) + mdAlg = "SHA-256"; + else if ("http://www.w3.org/2001/04/xmlenc#sha224 ".equals(mdAlg)) + mdAlg = "SHA-224"; + else if ("http://www.w3.org/2001/04/xmldsig-more#sha224 ".equals(mdAlg)) + mdAlg = "SHA-224"; + else if ("http://www.w3.org/2001/04/xmldsig-more#sha384".equals(mdAlg)) + mdAlg = "SHA-384"; + else if ("http://www.w3.org/2001/04/xmlenc#sha512".equals(mdAlg)) + mdAlg = "SHA-512"; + else if ("http://www.w3.org/2001/04/xmldsig-more#md2 ".equals(mdAlg)) + mdAlg = "MD2"; + else if ("http://www.w3.org/2001/04/xmldsig-more#md5".equals(mdAlg)) + mdAlg = "MD5"; + else if ("http://www.w3.org/2001/04/xmlenc#ripemd160 ".equals(mdAlg)) + mdAlg = "RipeMD-160"; + MessageDigest md = MessageDigest.getInstance(mdAlg); + byte[] hdiDigest = md.digest(hdi); + if (log.isDebugEnabled()) + log.debug("Comparing digest values... "); + if (!Arrays.equals(hdiDigest, dsigRef.getDigestValue())) { + log.error("digest values differ: " + new String(hdiDigest) + ", " + new String(dsigRef.getDigestValue())); + throw new DigestException("Bad digest value for reference " + id + ": " + dsigRef.getDigestValue()); + } + hashDataInputs.add(new ByteArrayHashDataInput(hdi, id, mimeType, encoding)); + } + return hashDataInputs; + } + + @Override + public SMCCSTALRequestHandler newInstance() { + return new WSSignRequestHandler(this.sessId, this.stalPort); + } } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java b/BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java new file mode 100644 index 00000000..b0285345 --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java @@ -0,0 +1,58 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package at.gv.egiz.stal.impl; + +import at.gv.egiz.stal.HashDataInput; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * + * @author clemens + */ +public class ByteArrayHashDataInput implements HashDataInput { + + protected byte[] hashData; + protected String id; + protected String mimeType; + protected String encoding; + + public ByteArrayHashDataInput(byte[] hashData, String id, String mimeType, String encoding) { + if (hashData == null) { + throw new NullPointerException("HashDataInput not provided."); + } + this.hashData = hashData; + this.id = id; + this.mimeType = mimeType; + this.encoding = encoding; + } + + @Override + public String getReferenceId() { + return id; + } + + @Override + public String getMimeType() { + return mimeType; + } + + @Override + public InputStream getHashDataInput() { + return new ByteArrayInputStream(hashData); + } + + /** + * may be null + * @return + */ + @Override + public String getEncoding() { + return encoding; + } + + +} diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java index f8546e49..a288a716 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java @@ -29,7 +29,10 @@ import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; import at.gv.egiz.stal.signedinfo.ReferenceType; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; /** * @@ -55,7 +58,7 @@ public class LocalSignRequestHandler extends SignRequestHandler { } @Override - protected List getHashDataInputs( + public List getCashedHashDataInputs( List dsigReferences) throws Exception { ArrayList result = new ArrayList(); for (ReferenceType dsigRef : dsigReferences) { @@ -65,7 +68,14 @@ public class LocalSignRequestHandler extends SignRequestHandler { if (dsigRefId != null) { for (HashDataInput hdi : hashDataInput) { if (hdi.getReferenceId().equals(dsigRefId)) { - result.add(hdi); + InputStream hdIs = hdi.getHashDataInput(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(hdIs.available()); + int b; + while ((b = hdIs.read()) != -1) { + baos.write(b); + } + ByteArrayHashDataInput baHdi = new ByteArrayHashDataInput(baos.toByteArray(), hdi.getReferenceId(), hdi.getMimeType(), hdi.getEncoding()); + result.add(baHdi); } } } else { diff --git a/STALService/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java b/STALService/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java deleted file mode 100644 index b0285345..00000000 --- a/STALService/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -package at.gv.egiz.stal.impl; - -import at.gv.egiz.stal.HashDataInput; -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -/** - * - * @author clemens - */ -public class ByteArrayHashDataInput implements HashDataInput { - - protected byte[] hashData; - protected String id; - protected String mimeType; - protected String encoding; - - public ByteArrayHashDataInput(byte[] hashData, String id, String mimeType, String encoding) { - if (hashData == null) { - throw new NullPointerException("HashDataInput not provided."); - } - this.hashData = hashData; - this.id = id; - this.mimeType = mimeType; - this.encoding = encoding; - } - - @Override - public String getReferenceId() { - return id; - } - - @Override - public String getMimeType() { - return mimeType; - } - - @Override - public InputStream getHashDataInput() { - return new ByteArrayInputStream(hashData); - } - - /** - * may be null - * @return - */ - @Override - public String getEncoding() { - return encoding; - } - - -} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 56c8340b..ac2b725c 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -45,7 +45,7 @@ public abstract class AbstractSMCCSTAL implements STAL { static { addRequestHandler(InfoboxReadRequest.class, new InfoBoxReadRequestHandler()); - addRequestHandler(SignRequest.class, new SignRequestHandler()); +// addRequestHandler(SignRequest.class, new SignRequestHandler()); } /** diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/CashedHashDataInputResolver.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/CashedHashDataInputResolver.java new file mode 100644 index 00000000..05af85d9 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/CashedHashDataInputResolver.java @@ -0,0 +1,27 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package at.gv.egiz.bku.smccstal; + +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; +import at.gv.egiz.stal.signedinfo.ReferenceType; +import java.security.DigestException; +import java.util.List; +import java.util.Set; + +/** + * + * @author clemens + */ +public interface CashedHashDataInputResolver { + + /** + * implementations may verify the hashvalue + * @post-condition returned list != null + * @return + */ + List getCashedHashDataInputs(List signedReferences) throws DigestException, Exception; +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index d37d0551..59eed55f 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -21,8 +21,6 @@ import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; @@ -43,21 +41,26 @@ import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; import at.gv.egiz.stal.SignResponse; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; import at.gv.egiz.stal.signedinfo.ObjectFactory; import at.gv.egiz.stal.signedinfo.ReferenceType; import at.gv.egiz.stal.signedinfo.SignedInfoType; import at.gv.egiz.stal.util.JCEAlgorithmNames; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.security.DigestException; +import java.security.DigestInputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Set; /** * This class is NOT thread-safe. * handleRequest() sets the SignedInfo which is used in providePIN. */ -public class SignRequestHandler extends AbstractRequestHandler implements - PINProvider { +public abstract class SignRequestHandler extends AbstractRequestHandler implements + CashedHashDataInputResolver { private static Log log = LogFactory.getLog(SignRequestHandler.class); private static JAXBContext jaxbContext; @@ -71,10 +74,10 @@ public class SignRequestHandler extends AbstractRequestHandler implements } } /** the SignedInfo of the current SignRequest */ - protected SignedInfoType signedInfo; - protected List hashDataInputs; +// protected SignedInfoType signedInfo; +// protected List hashDataInputs; - private int retryCounter = 0; +// private int retryCounter = 0; @SuppressWarnings("unchecked") @Override @@ -86,8 +89,7 @@ public class SignRequestHandler extends AbstractRequestHandler implements Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); InputStream is = new ByteArrayInputStream(signReq.getSignedInfo()); JAXBElement si = (JAXBElement) unmarshaller.unmarshal(is); - signedInfo = si.getValue(); - String signatureMethod = signedInfo.getSignatureMethod().getAlgorithm(); + String signatureMethod = si.getValue().getSignatureMethod().getAlgorithm(); log.debug("Found signature method: " + signatureMethod); String jceName = JCEAlgorithmNames.getJCEHashName(signatureMethod); if (jceName == null) { @@ -97,7 +99,7 @@ public class SignRequestHandler extends AbstractRequestHandler implements MessageDigest md = MessageDigest.getInstance(jceName); md.update(signReq.getSignedInfo()); KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); - byte[] resp = card.createSignature(md.digest(), kb, this); + byte[] resp = card.createSignature(md.digest(), kb, new STALPinProvider(si.getValue())); if (resp == null) { return new ErrorResponse(6001); } @@ -116,9 +118,7 @@ public class SignRequestHandler extends AbstractRequestHandler implements } catch (NoSuchAlgorithmException e) { log.error(e); return new ErrorResponse(1000); - } finally { - signedInfo = null; - } + } } else { log.fatal("Got unexpected STAL request: " + request); return new ErrorResponse(1000); @@ -130,59 +130,210 @@ public class SignRequestHandler extends AbstractRequestHandler implements return true; } - @Override - public String providePIN(PINSpec spec, int retries) { - if (retryCounter++ > 0) { - log.info("PIN wrong retrying ..."); - gui.showSignaturePINRetryDialog(spec, retries, this, "sign", this, - "cancel", this, "hashData"); - } else { - gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, - "hashData"); - } - do { - waitForAction(); - if (actionCommand.equals("cancel")) { - return null; - } else if (actionCommand.equals("hashData")) { - if (signedInfo != null) { - try { - gui.showWaitDialog(null); - if (hashDataInputs == null || hashDataInputs.size() == 0) { - hashDataInputs = getHashDataInputs(signedInfo.getReference()); - } - gui.showHashDataInputDialog(hashDataInputs, this, "ok"); - } catch (Exception ex) { - //FIXME localize messages - log.error("Failed to obtain HashDataInputs: " + ex.getMessage()); - gui.showErrorDialog("Failed to obtain HashDataInputs: " + ex.getMessage(), this, "ok"); - } - } else { - //FIXME get all hashdatainputs - gui.showErrorDialog("Failed to obtain HashDataInputs: No dsig:SignedInfo provided.", this, "ok"); - } - } else if (actionCommand.equals("sign")) { - return new String(gui.getPin()); - } else if (actionCommand.equals("ok")) { - gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, - "hashData"); - } - } while (true); - } +// @Override +// public String providePIN(PINSpec spec, int retries) { +// if (retryCounter++ > 0) { +// log.info("PIN wrong retrying ..."); +// gui.showSignaturePINRetryDialog(spec, retries, this, "sign", this, +// "cancel", this, "hashData"); +// } else { +// gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, +// "hashData"); +// } +// do { +// waitForAction(); +// if (actionCommand.equals("cancel")) { +// return null; +// } else if (actionCommand.equals("hashData")) { +// if (signedInfo != null) { +// try { +// gui.showWaitDialog(null); +// if (hashDataInputs == null || hashDataInputs.size() == 0) { +// HashMap signedReferences = new HashMap(); +// for (ReferenceType reference : signedInfo.getReference()) { +// //don't get Manifest, QualifyingProperties, ... +// if (reference.getType() == null) { +// signedReferences.put(reference.getId(), reference); +// } +// } +// hashDataInputs = getHashDataInputs(signedReferences.keySet()); +// for (HashDataInput hashDataInput : hashDataInputs) { +// ReferenceType reference = signedReferences.get(hashDataInput.getReferenceId()); +// String algorithm = reference.getDigestMethod().getAlgorithm(); +// MessageDigest md = MessageDigest.getInstance(algorithm); +// DigestInputStream dis = new DigestInputStream(hashDataInput.getHashDataInput(), md); +// while(dis.read() != -1) ; +// byte[] digestValue = md.digest(); +// boolean valid = reference.getDigestValue().equals(digestValue); +// } +// } +// gui.showHashDataInputDialog(hashDataInputs, this, "ok"); +// } catch (Exception ex) { +// //FIXME localize messages +// log.error("Failed to obtain HashDataInputs: " + ex.getMessage()); +// gui.showErrorDialog("Failed to obtain HashDataInputs: " + ex.getMessage(), this, "ok"); +// } +// } else { +// //FIXME get all hashdatainputs +// gui.showErrorDialog("Failed to obtain HashDataInputs: No dsig:SignedInfo provided.", this, "ok"); +// } +// } else if (actionCommand.equals("sign")) { +// return new String(gui.getPin()); +// } else if (actionCommand.equals("ok")) { +// gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this, +// "hashData"); +// } +// } while (true); +// } - @Override - public SMCCSTALRequestHandler newInstance() { - return new SignRequestHandler(); - } +// @Override +// public SMCCSTALRequestHandler newInstance() { +// return new SignRequestHandler(); +// } /** - * override by subclass + * implementations may verify the hashvalue * @post-condition returned list != null * @return */ - protected List getHashDataInputs(List signedReferences) throws Exception { - //TODO - log.warn("Return empty HashDataInput"); - return new ArrayList(); + @Override + public abstract List getCashedHashDataInputs(List signedReferences) throws Exception; +// { +// //TODO +// log.warn("Return empty HashDataInput"); +// return new ArrayList(); +// } + + + +// protected void validateHashDataInputs(List signedReferences, List hashDataInputs) { +// if (hashDataInputs != null) { +// +// Map hashDataIdMap = new HashMap(); +// for (HashDataInput hdi : hashDataInputs) { +// if (log.isTraceEnabled()) { +// log.trace("Provided HashDataInput for reference " + hdi.getReferenceId()); +// } +// hashDataIdMap.put(hdi.getReferenceId(), hdi); +// } +// +// List reqRefs = request.getReference(); +// for (GetHashDataInputType.Reference reqRef : reqRefs) { +// String reqRefId = reqRef.getID(); +// HashDataInput reqHdi = hashDataIdMap.get(reqRefId); +// if (reqHdi == null) { +// String msg = "Failed to resolve HashDataInput for reference " + reqRefId; +// log.error(msg); +// GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); +// faultInfo.setErrorCode(1); +// faultInfo.setErrorMessage(msg); +// throw new GetHashDataInputFault(msg, faultInfo); +// } +// +// InputStream hashDataIS = reqHdi.getHashDataInput(); +// if (hashDataIS == null) { +// //HashDataInput not cached? +// String msg = "Failed to obtain HashDataInput for reference " + reqRefId + ", reference not cached"; +// log.error(msg); +// GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); +// faultInfo.setErrorCode(1); +// faultInfo.setErrorMessage(msg); +// throw new GetHashDataInputFault(msg, faultInfo); +// } +// ByteArrayOutputStream baos = null; +// try { +// if (log.isDebugEnabled()) { +// log.debug("Resolved HashDataInput " + reqRefId + " (" + reqHdi.getMimeType() + ";charset=" + reqHdi.getEncoding() + ")"); +// } +// baos = new ByteArrayOutputStream(hashDataIS.available()); +// int c; +// while ((c = hashDataIS.read()) != -1) { +// baos.write(c); +// } +// GetHashDataInputResponseType.Reference ref = new GetHashDataInputResponseType.Reference(); +// ref.setID(reqRefId); +// ref.setMimeType(reqHdi.getMimeType()); +// ref.setEncoding(reqHdi.getEncoding()); +// ref.setValue(baos.toByteArray()); +// response.getReference().add(ref); +// } catch (IOException ex) { +// String msg = "Failed to get HashDataInput for reference " + reqRefId; +// log.error(msg, ex); +// GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); +// faultInfo.setErrorCode(1); +// faultInfo.setErrorMessage(msg); +// throw new GetHashDataInputFault(msg, faultInfo, ex); +// } finally { +// try { +// baos.close(); +// } catch (IOException ex) { +// } +// } +// } +// return response; +// } +// for (ReferenceType reference : signedReferences) { +// String algorithm = reference.getDigestMethod().getAlgorithm(); +// +// } +// } + + + /** + * cashes the HashDataInputs provided by SignRequestHandler.this.getHashDataInputs() + * (don't know whether outer class is LocalSignRequestHandler or WSSignRequestHandler, providing DataObjectHDI or ByteArrayHDI, resp) + */ + class STALPinProvider implements PINProvider { + + protected SignedInfoType signedInfo; + protected List hashDataInputs; + private int retryCounter = 0; + + public STALPinProvider(SignedInfoType signedInfo) { + this.signedInfo = signedInfo; + } + + @Override + public String providePIN(PINSpec spec, int retries) { + if (retryCounter++ > 0) { + log.info("PIN wrong retrying ..."); + gui.showSignaturePINRetryDialog(spec, retries, SignRequestHandler.this, "sign", SignRequestHandler.this, + "cancel", SignRequestHandler.this, "hashData"); + } else { + gui.showSignaturePINDialog(spec, SignRequestHandler.this, "sign", SignRequestHandler.this, "cancel", SignRequestHandler.this, + "hashData"); } + do { + waitForAction(); + if (actionCommand.equals("cancel")) { + return null; + } else if (actionCommand.equals("hashData")) { + if (signedInfo != null) { + try { + gui.showWaitDialog(null); + if (hashDataInputs == null || hashDataInputs.size() == 0) { + hashDataInputs = getCashedHashDataInputs(signedInfo.getReference()); + } + gui.showHashDataInputDialog(hashDataInputs, SignRequestHandler.this, "ok"); + } catch (DigestException ex) { + log.error("Bad digest value: " + ex.getMessage()); + gui.showErrorDialog(ex.getMessage()); + } catch (Exception ex) { + //FIXME localize messages + log.error("Failed to obtain HashDataInputs: " + ex.getMessage()); + gui.showErrorDialog("Failed to obtain HashDataInputs: " + ex.getMessage(), SignRequestHandler.this, "ok"); + } + } else { + //FIXME get all hashdatainputs + gui.showErrorDialog("Failed to obtain HashDataInputs: No dsig:SignedInfo provided.", SignRequestHandler.this, "ok"); + } + } else if (actionCommand.equals("sign")) { + return new String(gui.getPin()); + } else if (actionCommand.equals("ok")) { + gui.showSignaturePINDialog(spec, SignRequestHandler.this, "sign", SignRequestHandler.this, "cancel", SignRequestHandler.this, + "hashData"); + } + } while (true); + } + } } -- cgit v1.2.3 From 1c4df47223a6d655b9fb7f46f807171ceda07ba7 Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 23 Sep 2008 12:09:10 +0000 Subject: bitte warten... git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@56 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/bku/gui/BKUGUI.java | 12 +- BKUOnline/src/main/webapp/expired.html | 23 +- smccSTAL/pom.xml | 1 - .../bku/smccstal/InfoBoxReadRequestHandler.java | 249 +++++++++++---------- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 1 + 5 files changed, 146 insertions(+), 140 deletions(-) (limited to 'smccSTAL/src') diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java index b94a58e8..0b68962c 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java @@ -400,7 +400,8 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createSequentialGroup() // mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(errorMsgLabel)); //, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); + .addComponent(errorMsgLabel) + .addContainerGap()); //, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() // mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) @@ -777,10 +778,13 @@ public class BKUGUI implements BKUGUIFacade { mainPanel.setLayout(mainPanelLayout); mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(errorMsgLabel, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); + mainPanelLayout.createSequentialGroup() +// mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(errorMsgLabel) //, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); + .addContainerGap()); mainPanelLayout.setVerticalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + mainPanelLayout.createSequentialGroup() +// mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(errorMsgLabel)); JButton okButton = new JButton(); diff --git a/BKUOnline/src/main/webapp/expired.html b/BKUOnline/src/main/webapp/expired.html index 67ca94bc..2bb961f5 100644 --- a/BKUOnline/src/main/webapp/expired.html +++ b/BKUOnline/src/main/webapp/expired.html @@ -14,15 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - - -Session Expired - - -

- Ihre Sitzung ist abgelaufen. Ein neuer BKU request kann im Requestformular erstellt werden. -

- + + + + +Session Expired + + +

+ Ihre Sitzung ist abgelaufen. + +

+ \ No newline at end of file diff --git a/smccSTAL/pom.xml b/smccSTAL/pom.xml index 8b1a24b0..a053b419 100644 --- a/smccSTAL/pom.xml +++ b/smccSTAL/pom.xml @@ -11,7 +11,6 @@ smccSTAL smcc STAL 1.0-SNAPSHOT - at.gv.egiz diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java index 7dc2e202..25085b16 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java @@ -14,127 +14,128 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.bku.smccstal; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.smcc.SignatureCard; -import at.gv.egiz.smcc.SignatureCardException; -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.InfoboxReadRequest; -import at.gv.egiz.stal.InfoboxReadResponse; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; - -public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements - PINProvider { - - private static Log log = LogFactory.getLog(InfoBoxReadRequestHandler.class); - - private int retryCounter = 0; - - @Override - public STALResponse handleRequest(STALRequest request) { - if (request instanceof InfoboxReadRequest) { - InfoboxReadRequest infoBox = (InfoboxReadRequest) request; - try { - if (infoBox.getInfoboxIdentifier().equals("IdentityLink")) { - newSTALMessage("Message.RequestCaption", "Message.IdentityLink"); - log.debug("Handling identitylink infobox"); - byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this, - infoBox.getDomainIdentifier()); - if (resp == null) { - log.info("Got null as result->user cancelled"); - return new ErrorResponse(6001); - } else { - try { - resp = DomainIdConverter.convertDomainId(resp, infoBox - .getDomainIdentifier()); - } catch (Exception e) { - log.error("Cannot convert domain specific id", e); - return new ErrorResponse(1000); - } - } - InfoboxReadResponse stalResp = new InfoboxReadResponse(); - stalResp.setInfoboxValue(resp); - return stalResp; - } else if (SignatureCard.KeyboxName.CERITIFIED_KEYPAIR.equals(infoBox - .getInfoboxIdentifier())) { - newSTALMessage("Message.RequestCaption", "Message.CertifiedKeypair"); - log.debug("Handling certified keypair infobox"); - byte[] resp = card - .getCertificate(SignatureCard.KeyboxName.CERITIFIED_KEYPAIR); - if (resp == null) { - return new ErrorResponse(6001); - } - InfoboxReadResponse stalResp = new InfoboxReadResponse(); - stalResp.setInfoboxValue(resp); - return stalResp; - } else if (SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR - .equals(infoBox.getInfoboxIdentifier())) { - newSTALMessage("Message.RequestCaption", - "Message.SecureSignatureKeypair"); - log.debug("Handling secure signature keypair infobox"); - byte[] resp = card - .getCertificate(SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR); - if (resp == null) { - return new ErrorResponse(6001); - } - InfoboxReadResponse stalResp = new InfoboxReadResponse(); - stalResp.setInfoboxValue(resp); - return stalResp; - } else { - newSTALMessage("Message.RequestCaption", "Message.InfoboxReadRequest"); - log.warn("Unknown infobox identifier: " - + infoBox.getInfoboxIdentifier() + " trying generic request"); - byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this, - infoBox.getDomainIdentifier()); - if (resp == null) { - return new ErrorResponse(6001); - } - InfoboxReadResponse stalResp = new InfoboxReadResponse(); - stalResp.setInfoboxValue(resp); - return stalResp; - } - } catch (CancelledException cx) { - log.debug("User cancelled request", cx); - return new ErrorResponse(6001); - } catch (SignatureCardException e) { - log.info("Error while reading infobox: " + e); - return new ErrorResponse(4000); - } - } else { - log.fatal("Got unexpected STAL request: " + request); - return new ErrorResponse(1000); - } - } - - @Override - public boolean requireCard() { - return true; - } - - @Override - public String providePIN(PINSpec spec, int retries) { - if (retryCounter++ > 0) { - log.info("PIN wrong retrying ..."); - gui.showCardPINRetryDialog(spec, retries, this, "ok", this, "cancel"); - } else { - gui.showCardPINDialog(spec, this, "ok", this, "cancel"); - } - waitForAction(); - if (actionCommand.equals("cancel")) { - return null; - } - return new String(gui.getPin()); - } - - @Override - public SMCCSTALRequestHandler newInstance() { - return new InfoBoxReadRequestHandler(); - } -} +package at.gv.egiz.bku.smccstal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.InfoboxReadResponse; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements + PINProvider { + + private static Log log = LogFactory.getLog(InfoBoxReadRequestHandler.class); + + private int retryCounter = 0; + + @Override + public STALResponse handleRequest(STALRequest request) { + if (request instanceof InfoboxReadRequest) { + InfoboxReadRequest infoBox = (InfoboxReadRequest) request; + try { + if (infoBox.getInfoboxIdentifier().equals("IdentityLink")) { + newSTALMessage("Message.RequestCaption", "Message.IdentityLink"); + log.debug("Handling identitylink infobox"); + byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this, + infoBox.getDomainIdentifier()); + if (resp == null) { + log.info("Got null as result->user cancelled"); + return new ErrorResponse(6001); + } else { + try { + resp = DomainIdConverter.convertDomainId(resp, infoBox + .getDomainIdentifier()); + } catch (Exception e) { + log.error("Cannot convert domain specific id", e); + return new ErrorResponse(1000); + } + } + InfoboxReadResponse stalResp = new InfoboxReadResponse(); + stalResp.setInfoboxValue(resp); + return stalResp; + } else if (SignatureCard.KeyboxName.CERITIFIED_KEYPAIR.equals(infoBox + .getInfoboxIdentifier())) { + newSTALMessage("Message.RequestCaption", "Message.CertifiedKeypair"); + log.debug("Handling certified keypair infobox"); + byte[] resp = card + .getCertificate(SignatureCard.KeyboxName.CERITIFIED_KEYPAIR); + if (resp == null) { + return new ErrorResponse(6001); + } + InfoboxReadResponse stalResp = new InfoboxReadResponse(); + stalResp.setInfoboxValue(resp); + return stalResp; + } else if (SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR + .equals(infoBox.getInfoboxIdentifier())) { + newSTALMessage("Message.RequestCaption", + "Message.SecureSignatureKeypair"); + log.debug("Handling secure signature keypair infobox"); + byte[] resp = card + .getCertificate(SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR); + if (resp == null) { + return new ErrorResponse(6001); + } + InfoboxReadResponse stalResp = new InfoboxReadResponse(); + stalResp.setInfoboxValue(resp); + return stalResp; + } else { + newSTALMessage("Message.RequestCaption", "Message.InfoboxReadRequest"); + log.warn("Unknown infobox identifier: " + + infoBox.getInfoboxIdentifier() + " trying generic request"); + byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this, + infoBox.getDomainIdentifier()); + if (resp == null) { + return new ErrorResponse(6001); + } + InfoboxReadResponse stalResp = new InfoboxReadResponse(); + stalResp.setInfoboxValue(resp); + return stalResp; + } + } catch (CancelledException cx) { + log.debug("User cancelled request", cx); + return new ErrorResponse(6001); + } catch (SignatureCardException e) { + log.info("Error while reading infobox: " + e); + return new ErrorResponse(4000); + } + } else { + log.fatal("Got unexpected STAL request: " + request); + return new ErrorResponse(1000); + } + } + + @Override + public boolean requireCard() { + return true; + } + + @Override + public String providePIN(PINSpec spec, int retries) { + if (retryCounter++ > 0) { + log.info("PIN wrong retrying ..."); + gui.showCardPINRetryDialog(spec, retries, this, "ok", this, "cancel"); + } else { + gui.showCardPINDialog(spec, this, "ok", this, "cancel"); + } + waitForAction(); + gui.showWaitDialog(null); + if (actionCommand.equals("cancel")) { + return null; + } + return new String(gui.getPin()); + } + + @Override + public SMCCSTALRequestHandler newInstance() { + return new InfoBoxReadRequestHandler(); + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 59eed55f..8f380eec 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -305,6 +305,7 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen } do { waitForAction(); + gui.showWaitDialog(null); if (actionCommand.equals("cancel")) { return null; } else if (actionCommand.equals("hashData")) { -- cgit v1.2.3 From 03f5ae9e9068168b294c042d68a58637e71a54ee Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 23 Sep 2008 14:09:02 +0000 Subject: bitte warten... git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@59 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java | 2 +- BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java | 3 ++- smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java index cd96a481..465bde78 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java @@ -283,7 +283,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, } break; case SMCCHelper.CARD_FOUND: - gui.showWaitDialog(null); +// gui.showWaitDialog(null); signatureCard = smccHelper.getSignatureCard(errorMessages.getLocale()); return false; } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java index 0b68962c..544b6eb3 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java @@ -246,7 +246,8 @@ public class BKUGUI implements BKUGUIFacade { headerPanelLayout.setHorizontalGroup( headerPanelLayout.createSequentialGroup() // headerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); + .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) + .addContainerGap()); headerPanelLayout.setVerticalGroup( headerPanelLayout.createSequentialGroup() // headerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 8f380eec..0b297283 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -311,7 +311,7 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen } else if (actionCommand.equals("hashData")) { if (signedInfo != null) { try { - gui.showWaitDialog(null); +// gui.showWaitDialog(null); if (hashDataInputs == null || hashDataInputs.size() == 0) { hashDataInputs = getCashedHashDataInputs(signedInfo.getReference()); } -- cgit v1.2.3 From 013d98da75991857ea6e243e7360745d8d7d9048 Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 24 Sep 2008 13:09:47 +0000 Subject: git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@63 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'smccSTAL/src') diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index ac2b725c..f3b94078 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -39,7 +39,7 @@ public abstract class AbstractSMCCSTAL implements STAL { private static Log log = LogFactory.getLog(AbstractSMCCSTAL.class); protected Locale locale = Locale.getDefault(); - protected SMCCHelper smccHelper = new SMCCHelper(); +// protected SMCCHelper smccHelper = new SMCCHelper(); protected SignatureCard signatureCard = null; protected static Map handlerMap = new HashMap(); -- cgit v1.2.3 From d0879e9058943c6afa1912ccbeae936db2811f26 Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 30 Sep 2008 13:54:54 +0000 Subject: backport to JAXWS2.0 STALService initial connect() git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@76 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/bku/online/applet/BKUWorker.java | 189 ++++++------ .../bku/online/applet/WSSignRequestHandler.java | 4 +- .../at/gv/egiz/stal/client/STALServiceTest.java | 20 +- BKUOnline/pom.xml | 37 ++- .../src/main/custom-binding/stalservice-custom.xml | 14 + .../src/main/custom-binding/staltypes-custom.xml | 27 +- .../egiz/stal/service/impl/STALRequestBroker.java | 8 +- .../stal/service/impl/STALRequestBrokerImpl.java | 324 +++++++++++++++------ .../gv/egiz/stal/service/impl/STALServiceImpl.java | 186 ++++++++---- BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.wsdl | 15 + BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.xsd | 227 ++++++++------- .../egiz/stal/service/STALRequestBrokerTest.java | 57 ++-- .../main/java/at/gv/egiz/stal/HashDataInput.java | 18 +- .../src/main/java/at/gv/egiz/stal/STALRequest.java | 13 +- .../main/java/at/gv/egiz/stal/STALResponse.java | 70 ++--- .../egiz/stal/service/GetHashDataInputFault.java | 22 +- .../stal/service/GetHashDataInputFaultType.java | 98 ------- .../stal/service/GetHashDataInputResponseType.java | 255 ---------------- .../gv/egiz/stal/service/GetHashDataInputType.java | 172 ----------- .../stal/service/GetNextRequestResponseType.java | 114 -------- .../gv/egiz/stal/service/GetNextRequestType.java | 114 -------- .../at/gv/egiz/stal/service/ObjectFactory.java | 212 -------------- .../java/at/gv/egiz/stal/service/STALPortType.java | 44 ++- .../java/at/gv/egiz/stal/service/STALService.java | 32 +- .../java/at/gv/egiz/stal/service/package-info.java | 18 -- .../egiz/stal/service/types/ErrorResponseType.java | 84 ++++++ .../service/types/GetHashDataInputFaultType.java | 82 ++++++ .../types/GetHashDataInputResponseType.java | 239 +++++++++++++++ .../stal/service/types/GetHashDataInputType.java | 156 ++++++++++ .../service/types/GetNextRequestResponseType.java | 106 +++++++ .../stal/service/types/GetNextRequestType.java | 106 +++++++ .../stal/service/types/InfoboxReadRequestType.java | 102 +++++++ .../service/types/InfoboxReadResponseType.java | 62 ++++ .../gv/egiz/stal/service/types/ObjectFactory.java | 199 +++++++++++++ .../egiz/stal/service/types/QuitRequestType.java | 32 ++ .../at/gv/egiz/stal/service/types/RequestType.java | 30 ++ .../gv/egiz/stal/service/types/ResponseType.java | 30 ++ .../egiz/stal/service/types/SignRequestType.java | 97 ++++++ .../egiz/stal/service/types/SignResponseType.java | 62 ++++ .../gv/egiz/stal/service/types/package-info.java | 2 + .../java/at/gv/egiz/stal/util/STALTranslator.java | 109 +++++++ pom.xml | 290 +++++++++--------- .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 7 +- 43 files changed, 2425 insertions(+), 1660 deletions(-) delete mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputFaultType.java delete mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputResponseType.java delete mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputType.java delete mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/GetNextRequestResponseType.java delete mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/GetNextRequestType.java delete mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/ObjectFactory.java delete mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/package-info.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/ErrorResponseType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputFaultType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputResponseType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestResponseType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/InfoboxReadRequestType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/InfoboxReadResponseType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/ObjectFactory.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/QuitRequestType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/RequestType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/ResponseType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/SignRequestType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/SignResponseType.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/service/types/package-info.java create mode 100644 STALService/src/main/java/at/gv/egiz/stal/util/STALTranslator.java (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java index 35fe652f..a87b04c4 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java @@ -34,23 +34,23 @@ import at.gv.egiz.bku.smccstal.AbstractSMCCSTAL; import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.util.SMCCHelper; -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.InfoboxReadRequest; import at.gv.egiz.stal.QuitRequest; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; -import at.gv.egiz.stal.SignRequest; -import at.gv.egiz.stal.service.GetNextRequestResponseType; -import at.gv.egiz.stal.service.GetNextRequestType; -import at.gv.egiz.stal.service.ObjectFactory; +import at.gv.egiz.stal.service.types.GetNextRequestResponseType; +import at.gv.egiz.stal.service.types.GetNextRequestType; +import at.gv.egiz.stal.service.types.ObjectFactory; import at.gv.egiz.stal.service.STALPortType; import at.gv.egiz.stal.service.STALService; +import at.gv.egiz.stal.service.types.ErrorResponseType; +import at.gv.egiz.stal.service.types.RequestType; +import at.gv.egiz.stal.service.types.ResponseType; +import at.gv.egiz.stal.util.STALTranslator; public class BKUWorker extends AbstractSMCCSTAL implements Runnable, - ActionListener, SMCCSTALRequestHandler { + ActionListener, SMCCSTALRequestHandler { private static Log log = LogFactory.getLog(BKUWorker.class); - protected BKUGUIFacade gui; protected BKUApplet parent; private STALPortType stalPort; @@ -65,7 +65,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, * must not be null */ public BKUWorker(BKUGUIFacade gui, BKUApplet parent, - ResourceBundle errorMessageBundle) { + ResourceBundle errorMessageBundle) { if ((gui == null) || (parent == null) || (errorMessageBundle == null)) { throw new NullPointerException("Parameter must not be set to null"); } @@ -73,7 +73,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, this.parent = parent; this.errorMessages = errorMessageBundle; addRequestHandler(QuitRequest.class, this); - // register SignRequestHandler once we have a webservice port + // register SignRequestHandler once we have a webservice port } /** @@ -111,7 +111,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, } log.debug("Found WSDL url: " + wsdlURL); QName endpointName = new QName("http://www.egiz.gv.at/wsdl/stal", - "STALService"); + "STALService"); STALService stal = new STALService(wsdlURL, endpointName); return stal.getSTALPort(); } @@ -135,49 +135,75 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, return; } try { - ObjectFactory factory = new ObjectFactory(); - GetNextRequestType nextRequest = factory.createGetNextRequestType(); - String sessionId = parent.getMyAppletParameter(BKUApplet.SESSION_ID); if (sessionId == null) { // use the testsession for testing sessionId = "TestSession"; } - nextRequest.setSessionId(sessionId); - addRequestHandler(SignRequest.class, new WSSignRequestHandler(sessionId, - stalPort)); + addRequestHandler(at.gv.egiz.stal.SignRequest.class, new WSSignRequestHandler(sessionId, stalPort)); + + ObjectFactory of = new ObjectFactory(); + GetNextRequestResponseType nextRequestResp = stalPort.connect(sessionId); do { - GetNextRequestResponseType resp = stalPort.getNextRequest(nextRequest); - log.info("Got " + resp.getRequest().size() + " requests from server."); - List stalRequests = resp.getRequest(); + List requests = nextRequestResp.getInfoboxReadRequestOrSignRequestOrQuitRequest(); + List stalRequests = STALTranslator.translateRequests(requests); + + if (log.isInfoEnabled()) { + StringBuilder sb = new StringBuilder("Received "); + sb.append(stalRequests.size()); + sb.append(" STAL requests: "); + for (STALRequest r : stalRequests) { + sb.append(r.getClass()); + sb.append(' '); + } + log.info(sb.toString()); + } + boolean handle = true; for (STALRequest request : stalRequests) { - if (request instanceof InfoboxReadRequest) { - InfoboxReadRequest infobx = (InfoboxReadRequest) request; - if (infobx.getInfoboxIdentifier().equals("IdentityLink")) { - if (infobx.getDomainIdentifier() == null) { - if (!InternalSSLSocketFactory.getInstance().isEgovAgency()) { - handle = false; - } + if (request instanceof at.gv.egiz.stal.InfoboxReadRequest) { + at.gv.egiz.stal.InfoboxReadRequest r = (at.gv.egiz.stal.InfoboxReadRequest) request; + String infoboxId = r.getInfoboxIdentifier(); + String domainId = r.getDomainIdentifier(); + if ("IdentityLink".equals(infoboxId) && domainId == null) { + if (!InternalSSLSocketFactory.getInstance().isEgovAgency()) { + handle = false; } } } } - List responses; + + List responses; if (handle) { - responses = handleRequest(stalRequests); + List stalResponses = handleRequest(stalRequests); + if (log.isInfoEnabled()) { + StringBuilder sb = new StringBuilder(stalResponses.size()); + sb.append(" STAL responses: "); + for (STALResponse r : stalResponses) { + sb.append(r.getClass()); + sb.append(' '); + } + log.info(sb.toString()); + } + responses = STALTranslator.fromSTAL(stalResponses); } else { - responses = new ArrayList(1); - responses.add(new ErrorResponse(6002)); + responses = new ArrayList(1); + ErrorResponseType err = new ErrorResponseType(); + err.setErrorCode(6002); +// err.setErrorMessage(); + responses.add(err); + } + + if (!finished) { + GetNextRequestType nextRequest = of.createGetNextRequestType(); + nextRequest.setSessionId(sessionId); + nextRequest.getInfoboxReadResponseOrSignResponseOrErrorResponse().addAll(responses); + nextRequestResp = stalPort.getNextRequest(nextRequest); } - log.info("Got " + responses.size() + " responses."); - nextRequest = factory.createGetNextRequestType(); - nextRequest.setSessionId(sessionId); - nextRequest.getResponse().addAll(responses); } while (!finished); log.info("Done " + Thread.currentThread().getName()); - // gui.showWelcomeDialog(); } catch (Exception ex) { + log.error(ex.getMessage(), ex); gui.showErrorDialog("Sorry, an internal error occured: " + ex.getMessage()); try { waitForAction(); @@ -196,20 +222,17 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, URL url = null; if (redirectURL != null) { try { - url = new URL(parent.getCodeBase(), redirectURL + ";jsessionid=" - + parent.getMyAppletParameter(BKUApplet.SESSION_ID)); + url = new URL(parent.getCodeBase(), redirectURL + ";jsessionid=" + parent.getMyAppletParameter(BKUApplet.SESSION_ID)); } catch (MalformedURLException ex) { - log.warn("Parameter 'redirectURL': " + redirectURL - + " not a valid URL.", ex); - // gui.showErrorDialog(errorMsg, okListener, actionCommand) + log.warn("Parameter 'redirectURL': " + redirectURL + " not a valid URL.", ex); + // gui.showErrorDialog(errorMsg, okListener, actionCommand) } if (url != null) { if (redirectTarget == null) { log.info("Done. Trying to redirect to " + url + " ..."); parent.getAppletContext().showDocument(url); } else { - log.info("Done. Trying to redirect to " + url + " (target=" - + redirectTarget + ") ..."); + log.info("Done. Trying to redirect to " + url + " (target=" + redirectTarget + ") ..."); parent.getAppletContext().showDocument(url, redirectTarget); } } @@ -253,48 +276,48 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, int oldValue = SMCCHelper.PC_SC_NOT_SUPPORTED; // this is a save default while ((signatureCard == null) && (!actionPerformed)) { switch (smccHelper.getResultCode()) { - case SMCCHelper.PC_SC_NOT_SUPPORTED: - actionCommandList.clear(); - actionCommandList.add("ok"); - gui.showErrorDialog(errorMessages.getString("nopcscsupport"), this, - "ok"); - try { - waitForAction(); - } catch (InterruptedException e) { - log.error(e); - } - return true; - case SMCCHelper.TERMINAL_NOT_PRESENT: - actionCommandList.clear(); - actionCommandList.add("ok"); - gui.showErrorDialog(errorMessages.getString("nocardterminal"), this, - "ok"); - try { - waitForAction(); - } catch (InterruptedException e) { - log.error(e); - } - return true; - case SMCCHelper.CARD_NOT_SUPPORTED: - if (oldValue != SMCCHelper.CARD_NOT_SUPPORTED) { + case SMCCHelper.PC_SC_NOT_SUPPORTED: actionCommandList.clear(); - actionCommandList.add("cancel"); - gui.showCardNotSupportedDialog(this, "cancel"); - oldValue = SMCCHelper.CARD_NOT_SUPPORTED; - } - break; - case SMCCHelper.NO_CARD: - if (oldValue != SMCCHelper.NO_CARD) { + actionCommandList.add("ok"); + gui.showErrorDialog(errorMessages.getString("nopcscsupport"), this, + "ok"); + try { + waitForAction(); + } catch (InterruptedException e) { + log.error(e); + } + return true; + case SMCCHelper.TERMINAL_NOT_PRESENT: actionCommandList.clear(); - actionCommandList.add("cancel"); - gui.showInsertCardDialog(this, "cancel"); - oldValue = SMCCHelper.NO_CARD; - } - break; - case SMCCHelper.CARD_FOUND: - // gui.showWaitDialog(null); - signatureCard = smccHelper.getSignatureCard(errorMessages.getLocale()); - return false; + actionCommandList.add("ok"); + gui.showErrorDialog(errorMessages.getString("nocardterminal"), this, + "ok"); + try { + waitForAction(); + } catch (InterruptedException e) { + log.error(e); + } + return true; + case SMCCHelper.CARD_NOT_SUPPORTED: + if (oldValue != SMCCHelper.CARD_NOT_SUPPORTED) { + actionCommandList.clear(); + actionCommandList.add("cancel"); + gui.showCardNotSupportedDialog(this, "cancel"); + oldValue = SMCCHelper.CARD_NOT_SUPPORTED; + } + break; + case SMCCHelper.NO_CARD: + if (oldValue != SMCCHelper.NO_CARD) { + actionCommandList.clear(); + actionCommandList.add("cancel"); + gui.showInsertCardDialog(this, "cancel"); + oldValue = SMCCHelper.NO_CARD; + } + break; + case SMCCHelper.CARD_FOUND: + // gui.showWaitDialog(null); + signatureCard = smccHelper.getSignatureCard(errorMessages.getLocale()); + return false; } smccHelper.update(3000); } diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java index 6dae264c..5f422164 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java @@ -20,9 +20,9 @@ import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; import at.gv.egiz.bku.smccstal.SignRequestHandler; import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.impl.ByteArrayHashDataInput; -import at.gv.egiz.stal.service.GetHashDataInputResponseType; -import at.gv.egiz.stal.service.GetHashDataInputType; import at.gv.egiz.stal.service.STALPortType; +import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputType; import at.gv.egiz.stal.signedinfo.DigestMethodType; import at.gv.egiz.stal.signedinfo.ReferenceType; import java.security.DigestException; diff --git a/BKUApplet/src/test/java/at/gv/egiz/stal/client/STALServiceTest.java b/BKUApplet/src/test/java/at/gv/egiz/stal/client/STALServiceTest.java index 9b58798d..63da8225 100644 --- a/BKUApplet/src/test/java/at/gv/egiz/stal/client/STALServiceTest.java +++ b/BKUApplet/src/test/java/at/gv/egiz/stal/client/STALServiceTest.java @@ -33,12 +33,14 @@ import org.junit.Test; import at.gv.egiz.stal.InfoboxReadRequest; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.service.GetHashDataInputFault; -import at.gv.egiz.stal.service.GetHashDataInputResponseType; -import at.gv.egiz.stal.service.GetHashDataInputType; -import at.gv.egiz.stal.service.GetNextRequestResponseType; -import at.gv.egiz.stal.service.GetNextRequestType; import at.gv.egiz.stal.service.STALPortType; import at.gv.egiz.stal.service.STALService; +import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputType; +import at.gv.egiz.stal.service.types.GetNextRequestResponseType; +import at.gv.egiz.stal.service.types.GetNextRequestType; +import at.gv.egiz.stal.service.types.InfoboxReadRequestType; +import at.gv.egiz.stal.service.types.RequestType; /** * @@ -60,11 +62,11 @@ public class STALServiceTest { // req.getResponse().add(new ErrorResponse(1234)); GetNextRequestResponseType nrResp = port.getNextRequest(nrReq); assertNotNull(nrResp); - System.out.println("got response: " + nrResp.getRequest().size()); - for (STALRequest stalReq : nrResp.getRequest()) { - if (stalReq instanceof InfoboxReadRequest) { - String ibid = ((InfoboxReadRequest) stalReq).getInfoboxIdentifier(); - String did = ((InfoboxReadRequest) stalReq).getDomainIdentifier(); + System.out.println("got response: " + nrResp.getInfoboxReadRequestOrSignRequestOrQuitRequest().size()); + for (RequestType stalReq : nrResp.getInfoboxReadRequestOrSignRequestOrQuitRequest()) { + if (stalReq instanceof InfoboxReadRequestType) { + String ibid = ((InfoboxReadRequestType) stalReq).getInfoboxIdentifier(); + String did = ((InfoboxReadRequestType) stalReq).getDomainIdentifier(); System.out.println(" received InfoboxReadRequest for " + ibid + ", " + did); } else { System.out.println(" received STAL request " + stalReq.getClass().getName()); diff --git a/BKUOnline/pom.xml b/BKUOnline/pom.xml index e699d16b..5cdf5356 100644 --- a/BKUOnline/pom.xml +++ b/BKUOnline/pom.xml @@ -72,6 +72,7 @@ com.sun.xml.ws jaxws-rt 2.1.4 + - maven-war-plugin diff --git a/BKUOnline/src/main/custom-binding/stalservice-custom.xml b/BKUOnline/src/main/custom-binding/stalservice-custom.xml index 384b04f7..9c35cbdf 100644 --- a/BKUOnline/src/main/custom-binding/stalservice-custom.xml +++ b/BKUOnline/src/main/custom-binding/stalservice-custom.xml @@ -42,6 +42,20 @@ + + + + Initial connection, get the first request. + + + + + + + true + false + + diff --git a/BKUOnline/src/main/custom-binding/staltypes-custom.xml b/BKUOnline/src/main/custom-binding/staltypes-custom.xml index 2ea42082..3e150363 100644 --- a/BKUOnline/src/main/custom-binding/staltypes-custom.xml +++ b/BKUOnline/src/main/custom-binding/staltypes-custom.xml @@ -35,36 +35,13 @@ - + - + - - - - - - - - - - - - diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java index 560282ac..af886eec 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java @@ -22,8 +22,8 @@ package at.gv.egiz.stal.service.impl; import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.STAL; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.service.types.RequestType; +import at.gv.egiz.stal.service.types.ResponseType; import java.util.List; /** @@ -35,7 +35,9 @@ public interface STALRequestBroker extends STAL { public static final int ERR_6000 = 6000; public static final long DEFAULT_TIMEOUT_MS = 1000*60*5; //5mn - public List nextRequest(List response); + public List connect(); + + public List nextRequest(List response); public List getHashDataInput(); } diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java index dc3cc6d3..bfa83dd4 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java @@ -22,10 +22,17 @@ package at.gv.egiz.stal.service.impl; import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.InfoboxReadRequest; import at.gv.egiz.stal.QuitRequest; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.service.types.InfoboxReadRequestType; +import at.gv.egiz.stal.service.types.QuitRequestType; +import at.gv.egiz.stal.service.types.RequestType; +import at.gv.egiz.stal.service.types.ResponseType; +import at.gv.egiz.stal.service.types.SignRequestType; +import at.gv.egiz.stal.util.STALTranslator; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -48,18 +55,26 @@ public class STALRequestBrokerImpl implements STALRequestBroker { private static final Log log = LogFactory.getLog(STALRequestBrokerImpl.class); - private boolean expectingResponse = false; +// private boolean expectingResponse = false; private boolean interrupted = false; - private final RequestsMonitor reqMon = new RequestsMonitor(); - private final ResponsesMonitor respMon = new ResponsesMonitor(); +// private final RequestsMonitor reqMon = new RequestsMonitor(); +// private final ResponsesMonitor respMon = new ResponsesMonitor(); + + protected ArrayList requests; + protected ArrayList responses; + + protected ArrayList hashDataInputs; private long timeout; public STALRequestBrokerImpl(long timeoutMillisec) { if (timeoutMillisec <= 0) timeoutMillisec = DEFAULT_TIMEOUT_MS; - this.timeout = timeoutMillisec; + timeout = timeoutMillisec; + requests = new ArrayList(); + responses = new ArrayList(); + hashDataInputs = new ArrayList(); } /** @@ -73,52 +88,80 @@ public class STALRequestBrokerImpl implements STALRequestBroker { * @pre requests: either single SignRequest, QuitRequest or multiple ReadInfoboxRequests */ @Override - public List handleRequest(List requests) { + public List handleRequest(List stalRequests) { if (interrupted) { return null; } try { - synchronized (reqMon) { + synchronized (requests) { log.trace("produce request"); - reqMon.produce(requests); - reqMon.setHashDataInput(null); - for (STALRequest request : requests) { - if (request instanceof SignRequest) { - log.trace("Received SignRequest, keep HashDataInput."); - reqMon.setHashDataInput(((SignRequest) request).getHashDataInput()); - break; - } else if (request instanceof QuitRequest) { - log.trace("Received QuitRequest, do not wait for responses."); - log.trace("notifying request consumers"); - reqMon.notify(); - return new ArrayList(); - } else if (log.isTraceEnabled()) { - log.trace("Received STAL request: " + request.getClass().getName()); + requests.clear(); + hashDataInputs.clear(); +// reqMon.produce(requests); +// reqMon.setHashDataInput(null); + + for (STALRequest stalRequest : stalRequests) { + if (stalRequest instanceof SignRequest) { + log.trace("Received SignRequest, keep HashDataInput."); + SignRequestType req = new SignRequestType(); + req.setKeyIdentifier(((SignRequest) stalRequest).getKeyIdentifier()); + req.setSignedInfo(((SignRequest) stalRequest).getSignedInfo()); + requests.add(req); + hashDataInputs.addAll(((SignRequest) stalRequest).getHashDataInput()); + break; + } else if (stalRequest instanceof InfoboxReadRequest) { + log.trace("Received InfoboxReadRequest"); + InfoboxReadRequestType req = new InfoboxReadRequestType(); + req.setInfoboxIdentifier(((InfoboxReadRequest) stalRequest).getInfoboxIdentifier()); + req.setDomainIdentifier(((InfoboxReadRequest) stalRequest).getDomainIdentifier()); + requests.add(req); + } else if (stalRequest instanceof QuitRequest) { + log.trace("Received QuitRequest, do not wait for responses."); + requests.add(new QuitRequestType()); + log.trace("notifying request consumers"); + requests.notify(); +// reqMon.notify(); + return new ArrayList(); + } else { + log.error("Received unsupported STAL request: " + stalRequest.getClass().getName() + ", send QUIT"); + requests.clear(); + requests.add(new QuitRequestType()); + log.trace("notifying request consumers"); + requests.notify(); + return new ArrayList(); } } log.trace("notifying request consumers"); - reqMon.notify(); + requests.notify(); +// reqMon.notify(); } - synchronized (respMon) { + synchronized (responses) { //respMon) { long beforeWait = System.currentTimeMillis(); - while (respMon.responses == null) { +// while (respMon.responses == null) { + while (responses.isEmpty()) { log.trace("waiting to consume response"); - respMon.wait(timeout); +// respMon.wait(timeout); + responses.wait(timeout); if (System.currentTimeMillis() - beforeWait >= timeout) { log.warn("timeout while waiting to consume response, cleanup requests"); - reqMon.consume(); //TODO check deadlock? - reqMon.setHashDataInput(null); +// reqMon.consume(); //TODO check deadlock? +// reqMon.setHashDataInput(null); + requests.clear(); //TODO sync on requests? + hashDataInputs.clear(); return Collections.singletonList((STALResponse) new ErrorResponse(ERR_6000)); } } log.trace("consuming responses"); - List responses = respMon.consume(); +// List responses = respMon.consume(); + List resps = STALTranslator.toSTAL(responses); + responses.clear(); log.trace("notifying response producers"); - respMon.notify(); + responses.notify(); +// respMon.notify(); - return responses; + return resps; } } catch (InterruptedException ex) { log.warn("interrupt in handleRequest(): " + ex.getMessage()); @@ -127,6 +170,36 @@ public class STALRequestBrokerImpl implements STALRequestBroker { } } + @Override + public List connect() { + if (interrupted) { + return null; + } + try { + synchronized (requests) { + long beforeWait = System.currentTimeMillis(); + while (requests.isEmpty()) { + log.trace("waiting to consume request"); + requests.wait(timeout); + if (System.currentTimeMillis() - beforeWait >= timeout) { + log.warn("timeout while waiting to consume request"); + return Collections.singletonList((RequestType) new QuitRequestType()); + } + } + log.trace("consume request"); + List reqs = new ArrayList(); + reqs.addAll(requests); + + requests.clear(); + return reqs; + } + } catch (InterruptedException ex) { + log.warn("interrupt in nextRequest(): " + ex.getMessage()); + interrupted = true; + return null; + } + } + /** * This method is thread-safe, except for * an 'initial' call to nextRequest(null) followed by a @@ -139,63 +212,74 @@ public class STALRequestBrokerImpl implements STALRequestBroker { * @return QUIT if expected responses are not provided */ @Override - public List nextRequest(List responses) { + public List nextRequest(List resps) { if (interrupted) { return null; } try { - synchronized (respMon) { - if (responses != null && responses.size() > 0) { - if (!expectingResponse) { - log.warn("Received unexpected response in nextRequest(), return QUIT"); - return Collections.singletonList((STALRequest) new QuitRequest()); - } + synchronized (responses) { //respMon) { + if (resps != null && resps.size() > 0) { +// if (!expectingResponse) { +// log.warn("Received unexpected response in nextRequest(), return QUIT"); +// return Collections.singletonList((RequestType) new QuitRequestType()); +// } long beforeWait = System.currentTimeMillis(); - while (respMon.responses != null) { +// while (respMon.responses != null) { + while (!responses.isEmpty()) { log.trace("waiting to produce response"); - respMon.wait(timeout); +// respMon.wait(timeout); + responses.wait(timeout); if (System.currentTimeMillis() - beforeWait >= timeout) { log.warn("timeout while waiting to produce response"); - return Collections.singletonList((STALRequest) new QuitRequest()); + return Collections.singletonList((RequestType) new QuitRequestType()); } } log.trace("produce response"); - respMon.produce(responses); +// respMon.produce(resps); + responses.addAll(resps); //reset HashDataInputCallback iff SignResponse if (log.isTraceEnabled()) { - for (STALResponse response : responses) { + for (ResponseType response : resps) { log.trace("Received STAL response: " + response.getClass().getName()); } } log.trace("notifying response consumers"); - respMon.notify(); +// respMon.notify(); + responses.notify(); } else { - if (expectingResponse) { - log.warn("Did not receive expected response(s) in nextRequest(), return QUIT"); - return Collections.singletonList((STALRequest) new QuitRequest()); - } - log.trace("expecting non-null response in next nextRequest(response)"); - expectingResponse = true; +// if (expectingResponse) { +// log.warn("Did not receive expected response(s) in nextRequest(), return QUIT"); +// return Collections.singletonList((RequestType) new QuitRequestType()); +// } +// log.trace("expecting non-null response in next nextRequest(response)"); +// expectingResponse = true; + log.error("Received NextRequest without responses, return QUIT"); + return Collections.singletonList((RequestType) new QuitRequestType()); } } - synchronized (reqMon) { + synchronized (requests) { //reqMon) { long beforeWait = System.currentTimeMillis(); - while (reqMon.requests == null) { +// while (reqMon.requests == null) { + while (requests.isEmpty()) { log.trace("waiting to consume request"); - reqMon.wait(timeout); +// reqMon.wait(timeout); + requests.wait(timeout); if (System.currentTimeMillis() - beforeWait >= timeout) { log.warn("timeout while waiting to consume request"); - return Collections.singletonList((STALRequest) new QuitRequest()); + return Collections.singletonList((RequestType) new QuitRequestType()); } } log.trace("consume request"); - List requests = reqMon.consume(); - if (requests.size() > 0 && requests.get(0) instanceof QuitRequest) { - log.trace("expecting no response in next nextRequest()"); - expectingResponse = false; - } - return requests; + List reqs = new ArrayList(); // reqMon.consume(); + reqs.addAll(requests); + +// if (requests.size() > 0 && requests.get(0) instanceof QuitRequestType) { +// log.trace("expecting no response in next nextRequest()"); +// expectingResponse = false; +// } + requests.clear(); + return reqs; } } catch (InterruptedException ex) { log.warn("interrupt in nextRequest(): " + ex.getMessage()); @@ -205,49 +289,95 @@ public class STALRequestBrokerImpl implements STALRequestBroker { } @Override - public synchronized List getHashDataInput() { - log.trace("return " + reqMon.hashDataInput.size() + " current HashDataInput(s) "); - return reqMon.getHashDataInput(); + public List getHashDataInput() { + synchronized (requests) { + log.trace("return " + hashDataInputs.size() + " current HashDataInput(s) "); + return hashDataInputs; //reqMon.getHashDataInput(); + } } @Override public void setLocale(Locale locale) { } - class RequestsMonitor { - List requests; - List hashDataInput; - - void produce(List req) { - requests = req; - } - - synchronized List consume() { - List reqs = requests; - requests = null; - return reqs; - } - - void setHashDataInput(List hdi) { - hashDataInput = hdi; - } - - List getHashDataInput() { - return hashDataInput; - } - } - - class ResponsesMonitor { - List responses; - - void produce(List resp) { - responses = resp; - } - - synchronized List consume() { - List resps = responses; - responses = null; - return resps; - } - } +// class RequestsMonitor { +// List requests; +// List hashDataInput; +// +// void produce(List req) { +// requests = req; +// } +// +// synchronized List consume() { +// List reqs = new ArrayList(); +// for (STALRequest request : requests) { +// if (request instanceof SignRequest) { +// at.gv.egiz.stal.service.types.SignRequest r = new at.gv.egiz.stal.service.types.SignRequest(); +// r.setKeyIdentifier(((SignRequest) request).getKeyIdentifier()); +// r.setSignedInfo(((SignRequest) request).getSignedInfo()); +// reqs.add(r); +// } else if (request instanceof InfoboxReadRequest) { +// at.gv.egiz.stal.service.types.InfoboxReadRequest r = new at.gv.egiz.stal.service.types.InfoboxReadRequest(); +// r.setDomainIdentifier(((InfoboxReadRequest) request).getDomainIdentifier()); +// r.setInfoboxIdentifier(((InfoboxReadRequest) request).getInfoboxIdentifier()); +// reqs.add(r); +// } else if (request instanceof QuitRequest) { +// at.gv.egiz.stal.service.types.QuitRequest r = new at.gv.egiz.stal.service.types.QuitRequest(); +// reqs.add(r); +// } else { +// log.error("unknown STAL request type: " + request.getClass()); +// requests = null; +// return Collections.singletonList((at.gv.egiz.stal.service.types.STALRequest) new at.gv.egiz.stal.service.types.QuitRequest()); +// } +// } +// requests = null; +// return reqs; +// } +// +// void setHashDataInput(List hdi) { +// hashDataInput = hdi; +// } +// +// List getHashDataInput() { +// return hashDataInput; +// } +// } +// +// /** TODO: now, that responses are not nulled, synchronize directly on responses? */ +// class ResponsesMonitor { +// List responses; +// +// void produce(List resp) { +// responses = resp; +// } +// +// synchronized List consume() { +// List resps = new ArrayList(); +// +// for (at.gv.egiz.stal.service.types.STALResponse response : responses) { +// if (response instanceof at.gv.egiz.stal.service.types.InfoboxReadResponse) { +// InfoboxReadResponse r = new InfoboxReadResponse(); +// r.setInfoboxValue(((at.gv.egiz.stal.service.types.InfoboxReadResponse) response).getInfoboxValue()); +// resps.add(r); +// } else if (response instanceof at.gv.egiz.stal.service.types.SignResponse) { +// SignResponse r = new SignResponse(); +// r.setSignatureValue(((at.gv.egiz.stal.service.types.SignResponse) response).getSignatureValue()); +// resps.add(r); +// } else if (response instanceof at.gv.egiz.stal.service.types.ErrorResponse) { +// ErrorResponse r = new ErrorResponse(); +// r.setErrorCode(((at.gv.egiz.stal.service.types.ErrorResponse) response).getErrorCode()); +// r.setErrorMessage(((at.gv.egiz.stal.service.types.ErrorResponse) response).getErrorMessage()); +// resps.add(r); +// } else { +// log.error("unknown STAL response type: " + response.getClass()); +// ErrorResponse r = new ErrorResponse(4000); +// r.setErrorMessage("unknown STAL response type: " + response.getClass()); +// responses = null; +// return Collections.singletonList((STALResponse) r); +// } +// } +// responses = null; +// return resps; +// } +// } } diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java index d3d6c8db..bcee1e77 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java @@ -22,22 +22,27 @@ package at.gv.egiz.stal.service.impl; import at.gv.egiz.bku.binding.BindingProcessor; import at.gv.egiz.bku.binding.BindingProcessorManager; -import at.gv.egiz.stal.HashDataInput; -import at.gv.egiz.stal.service.*; import at.gv.egiz.bku.binding.Id; import at.gv.egiz.bku.binding.IdFactory; -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; -import at.gv.egiz.stal.InfoboxReadRequest; -import at.gv.egiz.stal.QuitRequest; -import at.gv.egiz.stal.SignRequest; - -import java.io.ByteArrayInputStream; + +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.service.GetHashDataInputFault; +import at.gv.egiz.stal.service.STALPortType; +import at.gv.egiz.stal.service.types.ErrorResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputFaultType; +import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputType; +import at.gv.egiz.stal.service.types.GetNextRequestResponseType; +import at.gv.egiz.stal.service.types.GetNextRequestType; +import at.gv.egiz.stal.service.types.InfoboxReadRequestType; +import at.gv.egiz.stal.service.types.QuitRequestType; +import at.gv.egiz.stal.service.types.RequestType; +import at.gv.egiz.stal.service.types.ResponseType; +import at.gv.egiz.stal.service.types.SignRequestType; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.Collections; +import java.nio.charset.Charset; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -63,57 +68,90 @@ public class STALServiceImpl implements STALPortType { WebServiceContext wsContext; protected IdFactory idF = IdFactory.getInstance(); + @Override - public GetNextRequestResponseType getNextRequest(GetNextRequestType request) { - - Id sessionId = idF.createId(request.getSessionId()); - - List responsesIn = request.getResponse(); - - GetNextRequestResponseType response = new GetNextRequestResponseType(); - response.setSessionId(sessionId.toString()); + public GetNextRequestResponseType connect(String sessId) { + + if (sessId == null) { + throw new NullPointerException("No session id provided"); + } + + Id sessionId = idF.createId(sessId); + if (log.isDebugEnabled()) { + log.debug("Received Connect [" + sessionId + "]"); + } + if (TEST_SESSION_ID.equals(sessionId)) { - if (responsesIn.size() > 0 && responsesIn.get(0) instanceof ErrorResponse) { - log.info("Received TestSession GetNextRequest(ErrorResponse), returning QuitRequest"); - response.getRequest().add(new QuitRequest()); - } else { - log.info("Received TestSession GetNextRequest, returning InfoboxReadRequest "); - SignRequest sig = new SignRequest(); - sig.setKeyIdentifier("SecureSignatureKeypair"); - sig.setSignedInfo(" id('signed-data-object-0-1214921968-27971781-13578')/node() H1IePEEfGQ2SG03H6LTzw1TpCuM=yV6Q+I60buqR4mMaxA7fi+CV35A=".getBytes()); - response.getRequest().add(sig); - InfoboxReadRequest req = new InfoboxReadRequest(); - req.setInfoboxIdentifier("IdentityLink"); - req.setDomainIdentifier("hansiwurzel"); - response.getRequest().add(req); - req = new InfoboxReadRequest(); - req.setInfoboxIdentifier("CertifiedKeypair"); - response.getRequest().add(req); - req = new InfoboxReadRequest(); - req.setInfoboxIdentifier("SecureSignatureKeypair"); - response.getRequest().add(req); - } - return response; + return getTestSessionNextRequestResponse(null); } + + GetNextRequestResponseType response = new GetNextRequestResponseType(); + response.setSessionId(sessionId.toString()); STALRequestBroker stal = getStal(sessionId); if (stal != null) { + + List requestsOut = ((STALRequestBroker) stal).connect(); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().addAll(requestsOut); + if (log.isDebugEnabled()) { - StringBuilder sb = new StringBuilder("Received GetNextRequest ["); + StringBuilder sb = new StringBuilder("Returning initial GetNextRequestResponse ["); sb.append(sessionId.toString()); sb.append("] containing "); - sb.append(responsesIn.size()); - sb.append(" responses: "); - for (STALResponse respIn : responsesIn) { - sb.append(respIn); + sb.append(requestsOut.size()); + sb.append(" requests: "); + for (RequestType reqOut : requestsOut) { + sb.append(reqOut.getClass()); sb.append(' '); } + log.debug(sb.toString()); } + } else { + log.error("Failed to get STAL for session " + sessionId + ", returning QuitRequest"); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(new QuitRequestType()); + } + return response; + } + + @Override + public GetNextRequestResponseType getNextRequest(GetNextRequestType request) { + + if (request.getSessionId() == null) { + throw new NullPointerException("No session id provided"); + } + + Id sessionId = idF.createId(request.getSessionId()); + + List responsesIn = request.getInfoboxReadResponseOrSignResponseOrErrorResponse();//getResponse(); + + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Received GetNextRequest ["); + sb.append(sessionId.toString()); + sb.append("] containing "); + sb.append(responsesIn.size()); + sb.append(" responses: "); + for (ResponseType respIn : responsesIn) { + sb.append(respIn.getClass()); + sb.append(' '); + } + log.debug(sb.toString()); + } + + if (TEST_SESSION_ID.equals(sessionId)) { + return getTestSessionNextRequestResponse(responsesIn); + } - List requestsOut = ((STALRequestBroker) stal).nextRequest(responsesIn); - response.getRequest().addAll(requestsOut); + GetNextRequestResponseType response = new GetNextRequestResponseType(); + response.setSessionId(sessionId.toString()); + + STALRequestBroker stal = getStal(sessionId); + + if (stal != null) { + + List requestsOut = ((STALRequestBroker) stal).nextRequest(responsesIn); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().addAll(requestsOut); if (log.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Returning GetNextRequestResponse ["); @@ -121,14 +159,15 @@ public class STALServiceImpl implements STALPortType { sb.append("] containing "); sb.append(requestsOut.size()); sb.append(" requests: "); - for (STALRequest reqOut : requestsOut) { - sb.append(reqOut); + for (RequestType reqOut : requestsOut) { + sb.append(reqOut.getClass()); sb.append(' '); } + log.debug(sb.toString()); } } else { log.error("Failed to get STAL for session " + sessionId + ", returning QuitRequest"); - response.getRequest().add(new QuitRequest()); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(new QuitRequestType()); } return response; } @@ -136,6 +175,10 @@ public class STALServiceImpl implements STALPortType { @Override public GetHashDataInputResponseType getHashDataInput(GetHashDataInputType request) throws GetHashDataInputFault { + if (request.getSessionId() == null) { + throw new NullPointerException("No session id provided"); + } + Id sessionId = idF.createId(request.getSessionId()); if (log.isDebugEnabled()) { @@ -150,8 +193,17 @@ public class STALServiceImpl implements STALPortType { GetHashDataInputResponseType.Reference ref = new GetHashDataInputResponseType.Reference(); ref.setID("Reference-" + TEST_SESSION_ID + "-001"); ref.setMimeType("text/plain"); - ref.setEncoding("UTF-8"); - ref.setValue("hashdatainput-öäüß@€-00000000001".getBytes()); + + Charset charset; + try { + charset = Charset.forName("iso-8859-15"); + ref.setEncoding("iso-8859-15"); + } catch (Exception ex) { + log.warn(ex.getMessage()); + charset = Charset.defaultCharset(); + ref.setEncoding(charset.toString()); + } + ref.setValue("hashdatainput-öäüß@€-00000000001".getBytes(charset)); response.getReference().add(ref); return response; } else { @@ -244,10 +296,40 @@ public class STALServiceImpl implements STALPortType { } private STALRequestBroker getStal(Id sessionId) { + if (log.isTraceEnabled()) { + log.trace("resolve STAL for session " + sessionId); + } MessageContext mCtx = wsContext.getMessageContext(); ServletContext sCtx = (ServletContext) mCtx.get(MessageContext.SERVLET_CONTEXT); BindingProcessorManager bpMgr = (BindingProcessorManager) sCtx.getAttribute(BINDING_PROCESSOR_MANAGER); BindingProcessor bp = bpMgr.getBindingProcessor(sessionId); return (bp == null) ? null : (bp.isFinished() ? null : (STALRequestBroker) bp.getSTAL()); } + + private GetNextRequestResponseType getTestSessionNextRequestResponse(List responsesIn) { + GetNextRequestResponseType response = new GetNextRequestResponseType(); + response.setSessionId(TEST_SESSION_ID.toString()); + + if (responsesIn != null && responsesIn.size() > 0 && responsesIn.get(0) instanceof ErrorResponseType) { + log.info("Received TestSession GetNextRequest(ErrorResponse), returning QuitRequest"); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(new QuitRequestType()); + } else { + log.info("Received TestSession GetNextRequest, returning InfoboxReadRequest "); + SignRequestType sig = new SignRequestType(); + sig.setKeyIdentifier("SecureSignatureKeypair"); + sig.setSignedInfo(" id('signed-data-object-0-1214921968-27971781-13578')/node() H1IePEEfGQ2SG03H6LTzw1TpCuM=yV6Q+I60buqR4mMaxA7fi+CV35A=".getBytes()); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(sig); + InfoboxReadRequestType req = new InfoboxReadRequestType(); + req.setInfoboxIdentifier("IdentityLink"); + req.setDomainIdentifier("hansiwurzel"); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(req); + req = new InfoboxReadRequestType(); + req.setInfoboxIdentifier("CertifiedKeypair"); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(req); + req = new InfoboxReadRequestType(); + req.setInfoboxIdentifier("SecureSignatureKeypair"); + response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(req); + } + return response; + } } diff --git a/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.wsdl b/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.wsdl index a9f16a12..344e5ce2 100644 --- a/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.wsdl +++ b/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.wsdl @@ -24,6 +24,9 @@ + + + @@ -40,6 +43,10 @@ + + + + @@ -52,6 +59,14 @@ + + + + + + + + diff --git a/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.xsd b/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.xsd index b3c4841a..6f3946dc 100644 --- a/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.xsd +++ b/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.xsd @@ -18,121 +18,136 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + - - + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BKUOnline/src/test/java/at/gv/egiz/stal/service/STALRequestBrokerTest.java b/BKUOnline/src/test/java/at/gv/egiz/stal/service/STALRequestBrokerTest.java index d6ce2720..8830a81c 100644 --- a/BKUOnline/src/test/java/at/gv/egiz/stal/service/STALRequestBrokerTest.java +++ b/BKUOnline/src/test/java/at/gv/egiz/stal/service/STALRequestBrokerTest.java @@ -32,6 +32,13 @@ import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignResponse; import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.service.types.InfoboxReadRequestType; +import at.gv.egiz.stal.service.types.InfoboxReadResponseType; +import at.gv.egiz.stal.service.types.QuitRequestType; +import at.gv.egiz.stal.service.types.RequestType; +import at.gv.egiz.stal.service.types.ResponseType; +import at.gv.egiz.stal.service.types.SignRequestType; +import at.gv.egiz.stal.service.types.SignResponseType; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -277,19 +284,19 @@ public class STALRequestBrokerTest { public void run() { try { log.debug("calling stal.nextRequest(oldResponse)"); - STALResponse oldResp = new InfoboxReadResponse(); - List requests = stal.nextRequest(Collections.singletonList(oldResp)); + ResponseType oldResp = new InfoboxReadResponseType(); + List requests = stal.nextRequest(Collections.singletonList(oldResp)); log.debug("got " + requests.size() + " requests. processing..."); Thread.sleep(1); - List responses = new ArrayList(); - for (STALRequest request : requests) { - if (request instanceof InfoboxReadRequest) { + List responses = new ArrayList(); + for (RequestType request : requests) { + if (request instanceof InfoboxReadRequestType) { log.debug("received UNEXPECTED READINFOBOX request"); - InfoboxReadResponse r = new InfoboxReadResponse(); + InfoboxReadResponseType r = new InfoboxReadResponseType(); r.setInfoboxValue("dummyInfobox".getBytes()); responses.add(r); - } else if (request instanceof SignRequest) { + } else if (request instanceof SignRequestType) { log.debug("received UNEXPECTED SIGN request"); @@ -304,10 +311,10 @@ public class STALRequestBrokerTest { log.debug("got HashDataInput " + new String(data)); - SignResponse r = new SignResponse(); + SignResponseType r = new SignResponseType(); r.setSignatureValue("dummySignature".getBytes()); responses.add(r); - } else if (request instanceof QuitRequest) { + } else if (request instanceof QuitRequestType) { log.debug("received EXPECTED QUIT request"); return; } @@ -319,8 +326,8 @@ public class STALRequestBrokerTest { // } log.debug("calling stal.nextRequest with " + responses.size() + " responses"); requests = stal.nextRequest(responses); - for (STALRequest request : requests) { - if (request instanceof QuitRequest) { + for (RequestType request : requests) { + if (request instanceof QuitRequestType) { log.debug("got QUIT request"); } else { log.debug("expected QUIT request, got " + request.getClass().getName()); @@ -342,16 +349,16 @@ public class STALRequestBrokerTest { try { // first call w/ empty response list log.debug("calling stal.nextRequest"); - List requests = stal.nextRequest(null); //new ArrayList()); + List requests = stal.nextRequest(null); //new ArrayList()); log.debug("got " + requests.size() + " requests. processing..."); Thread.sleep(1); - List responses = new ArrayList(); - for (STALRequest request : requests) { - if (request instanceof InfoboxReadRequest) { - InfoboxReadResponse r = new InfoboxReadResponse(); + List responses = new ArrayList(); + for (RequestType request : requests) { + if (request instanceof InfoboxReadRequestType) { + InfoboxReadResponseType r = new InfoboxReadResponseType(); r.setInfoboxValue("dummyInfobox".getBytes()); responses.add(r); - } else if (request instanceof SignRequest) { + } else if (request instanceof SignRequestType) { log.debug("calling stal.getCurrentHashDataInputCallback"); List hdis = stal.getHashDataInput(); @@ -364,10 +371,10 @@ public class STALRequestBrokerTest { log.debug("got HashDataInput " + new String(data)); - SignResponse r = new SignResponse(); + SignResponseType r = new SignResponseType(); r.setSignatureValue("dummySignature".getBytes()); responses.add(r); - } else if (request instanceof QuitRequest) { + } else if (request instanceof QuitRequestType) { log.debug("received UNEXPECTED QUIT request"); return; } @@ -379,8 +386,8 @@ public class STALRequestBrokerTest { // } log.debug("calling stal.nextRequest with " + responses.size() + " responses"); requests = stal.nextRequest(responses); - for (STALRequest request : requests) { - if (request instanceof QuitRequest) { + for (RequestType request : requests) { + if (request instanceof QuitRequestType) { log.debug("got QUIT request"); } else { log.debug("expected QUIT request, got " + request.getClass().getName()); @@ -401,12 +408,12 @@ public class STALRequestBrokerTest { try { // first call w/ empty response list log.debug("calling stal.nextRequest"); - List requests = stal.nextRequest(null); //new ArrayList()); + List requests = stal.nextRequest(null); //new ArrayList()); log.debug("got " + requests.size() + " requests. processing..."); Thread.sleep(1); - for (STALRequest request : requests) { + for (RequestType request : requests) { // if (request instanceof InfoboxReadRequest) { - if (request instanceof SignRequest) { + if (request instanceof SignRequestType) { log.debug("calling stal.getCurrentHashDataInputCallback"); List hdis = stal.getHashDataInput(); assertNotNull(hdis); @@ -416,7 +423,7 @@ public class STALRequestBrokerTest { byte[] data = new byte[hd.available()]; hd.read(data); log.debug("got HashDataInput " + new String(data)); - } else if (request instanceof QuitRequest) { + } else if (request instanceof QuitRequestType) { log.debug("received UNEXPECTED QUIT requests"); return; } diff --git a/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java b/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java index 1c648531..62c25fc4 100644 --- a/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java +++ b/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java @@ -1,7 +1,19 @@ /* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.stal; diff --git a/STAL/src/main/java/at/gv/egiz/stal/STALRequest.java b/STAL/src/main/java/at/gv/egiz/stal/STALRequest.java index 0c3f88c2..226ac277 100644 --- a/STAL/src/main/java/at/gv/egiz/stal/STALRequest.java +++ b/STAL/src/main/java/at/gv/egiz/stal/STALRequest.java @@ -19,7 +19,8 @@ package at.gv.egiz.stal; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlSeeAlso; +//import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlType; @@ -43,11 +44,11 @@ import javax.xml.bind.annotation.XmlType; */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "RequestType") -@XmlSeeAlso({ - SignRequest.class, - InfoboxReadRequest.class, - QuitRequest.class -}) +//@XmlSeeAlso({ +// SignRequest.class, +// InfoboxReadRequest.class, +// QuitRequest.class +//}) public abstract class STALRequest { diff --git a/STAL/src/main/java/at/gv/egiz/stal/STALResponse.java b/STAL/src/main/java/at/gv/egiz/stal/STALResponse.java index 91ef3c24..f561a2aa 100644 --- a/STAL/src/main/java/at/gv/egiz/stal/STALResponse.java +++ b/STAL/src/main/java/at/gv/egiz/stal/STALResponse.java @@ -22,7 +22,7 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlID; import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlSeeAlso; +//import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @@ -49,41 +49,41 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "ResponseType") -@XmlSeeAlso({ - ErrorResponse.class, - SignResponse.class, - InfoboxReadResponse.class -}) +//@XmlSeeAlso({ +// ErrorResponse.class, +// SignResponse.class, +// InfoboxReadResponse.class +//}) public abstract class STALResponse { - @XmlAttribute(name = "Id") - @XmlJavaTypeAdapter(CollapsedStringAdapter.class) - @XmlID - @XmlSchemaType(name = "ID") - protected String id; - - /** - * Gets the value of the id property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getId() { - return id; - } - - /** - * Sets the value of the id property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setId(String value) { - this.id = value; - } +// @XmlAttribute(name = "Id") +// @XmlJavaTypeAdapter(CollapsedStringAdapter.class) +// @XmlID +// @XmlSchemaType(name = "ID") +// protected String id; +// +// /** +// * Gets the value of the id property. +// * +// * @return +// * possible object is +// * {@link String } +// * +// */ +// public String getId() { +// return id; +// } +// +// /** +// * Sets the value of the id property. +// * +// * @param value +// * allowed object is +// * {@link String } +// * +// */ +// public void setId(String value) { +// this.id = value; +// } } diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputFault.java b/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputFault.java index 4db6a91c..df42ab47 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputFault.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputFault.java @@ -1,28 +1,14 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.service; import javax.xml.ws.WebFault; +import at.gv.egiz.stal.service.types.GetHashDataInputFaultType; + /** * This class was generated by the JAX-WS RI. * JAX-WS RI 2.1.3-b02- - * Generated source version: 2.1 + * Generated source version: 2.0 * */ @WebFault(name = "GetHashDataInputFault", targetNamespace = "http://www.egiz.gv.at/stal") @@ -60,7 +46,7 @@ public class GetHashDataInputFault /** * * @return - * returns fault bean: at.gv.egiz.stal.GetHashDataInputFaultType + * returns fault bean: at.gv.egiz.stal.service.types.GetHashDataInputFaultType */ public GetHashDataInputFaultType getFaultInfo() { return faultInfo; diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputFaultType.java b/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputFaultType.java deleted file mode 100644 index 5301a3bd..00000000 --- a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputFaultType.java +++ /dev/null @@ -1,98 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.service; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for GetHashDataInputFaultType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="GetHashDataInputFaultType">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="ErrorCode" type="{http://www.w3.org/2001/XMLSchema}int"/>
- *         <element name="ErrorMessage" type="{http://www.w3.org/2001/XMLSchema}string"/>
- *       </sequence>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "GetHashDataInputFaultType", propOrder = { - "errorCode", - "errorMessage" -}) -public class GetHashDataInputFaultType { - - @XmlElement(name = "ErrorCode") - protected int errorCode; - @XmlElement(name = "ErrorMessage", required = true) - protected String errorMessage; - - /** - * Gets the value of the errorCode property. - * - */ - public int getErrorCode() { - return errorCode; - } - - /** - * Sets the value of the errorCode property. - * - */ - public void setErrorCode(int value) { - this.errorCode = value; - } - - /** - * Gets the value of the errorMessage property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getErrorMessage() { - return errorMessage; - } - - /** - * Sets the value of the errorMessage property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setErrorMessage(String value) { - this.errorMessage = value; - } - -} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputResponseType.java deleted file mode 100644 index f02d1ce6..00000000 --- a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputResponseType.java +++ /dev/null @@ -1,255 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.service; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.XmlValue; - - -/** - *

Java class for GetHashDataInputResponseType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="GetHashDataInputResponseType">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="Reference" maxOccurs="unbounded">
- *           <complexType>
- *             <simpleContent>
- *               <extension base="<http://www.w3.org/2001/XMLSchema>base64Binary">
- *                 <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                 <attribute name="MimeType" type="{http://www.w3.org/2001/XMLSchema}string" />
- *                 <attribute name="Encoding" type="{http://www.w3.org/2001/XMLSchema}string" />
- *               </extension>
- *             </simpleContent>
- *           </complexType>
- *         </element>
- *       </sequence>
- *       <attribute name="sessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "GetHashDataInputResponseType", propOrder = { - "reference" -}) -public class GetHashDataInputResponseType { - - @XmlElement(name = "Reference", required = true) - protected List reference; - @XmlAttribute - protected String sessionId; - - /** - * Gets the value of the reference property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the reference property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getReference().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link GetHashDataInputResponseType.Reference } - * - * - */ - public List getReference() { - if (reference == null) { - reference = new ArrayList(); - } - return this.reference; - } - - /** - * Gets the value of the sessionId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSessionId() { - return sessionId; - } - - /** - * Sets the value of the sessionId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSessionId(String value) { - this.sessionId = value; - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-     * <complexType>
-     *   <simpleContent>
-     *     <extension base="<http://www.w3.org/2001/XMLSchema>base64Binary">
-     *       <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *       <attribute name="MimeType" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *       <attribute name="Encoding" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *     </extension>
-     *   </simpleContent>
-     * </complexType>
-     * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "", propOrder = { - "value" - }) - public static class Reference { - - @XmlValue - protected byte[] value; - @XmlAttribute(name = "ID") - protected String id; - @XmlAttribute(name = "MimeType") - protected String mimeType; - @XmlAttribute(name = "Encoding") - protected String encoding; - - /** - * Gets the value of the value property. - * - * @return - * possible object is - * byte[] - */ - public byte[] getValue() { - return value; - } - - /** - * Sets the value of the value property. - * - * @param value - * allowed object is - * byte[] - */ - public void setValue(byte[] value) { - this.value = ((byte[]) value); - } - - /** - * Gets the value of the id property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getID() { - return id; - } - - /** - * Sets the value of the id property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setID(String value) { - this.id = value; - } - - /** - * Gets the value of the mimeType property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getMimeType() { - return mimeType; - } - - /** - * Sets the value of the mimeType property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setMimeType(String value) { - this.mimeType = value; - } - - /** - * Gets the value of the encoding property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getEncoding() { - return encoding; - } - - /** - * Sets the value of the encoding property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setEncoding(String value) { - this.encoding = value; - } - - } - -} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputType.java b/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputType.java deleted file mode 100644 index 970b0744..00000000 --- a/STALService/src/main/java/at/gv/egiz/stal/service/GetHashDataInputType.java +++ /dev/null @@ -1,172 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.service; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for GetHashDataInputType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="GetHashDataInputType">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="Reference" maxOccurs="unbounded">
- *           <complexType>
- *             <complexContent>
- *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *                 <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
- *               </restriction>
- *             </complexContent>
- *           </complexType>
- *         </element>
- *       </sequence>
- *       <attribute name="sessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "GetHashDataInputType", propOrder = { - "reference" -}) -public class GetHashDataInputType { - - @XmlElement(name = "Reference", required = true) - protected List reference; - @XmlAttribute - protected String sessionId; - - /** - * Gets the value of the reference property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the reference property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getReference().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link GetHashDataInputType.Reference } - * - * - */ - public List getReference() { - if (reference == null) { - reference = new ArrayList(); - } - return this.reference; - } - - /** - * Gets the value of the sessionId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSessionId() { - return sessionId; - } - - /** - * Sets the value of the sessionId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSessionId(String value) { - this.sessionId = value; - } - - - /** - *

Java class for anonymous complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

-     * <complexType>
-     *   <complexContent>
-     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *       <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *     </restriction>
-     *   </complexContent>
-     * </complexType>
-     * 
- * - * - */ - @XmlAccessorType(XmlAccessType.FIELD) - @XmlType(name = "") - public static class Reference { - - @XmlAttribute(name = "ID") - protected String id; - - /** - * Gets the value of the id property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getID() { - return id; - } - - /** - * Sets the value of the id property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setID(String value) { - this.id = value; - } - - } - -} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/GetNextRequestResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/GetNextRequestResponseType.java deleted file mode 100644 index 7a723431..00000000 --- a/STALService/src/main/java/at/gv/egiz/stal/service/GetNextRequestResponseType.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.service; - -import at.gv.egiz.stal.STALRequest; -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for GetNextRequestResponseType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="GetNextRequestResponseType">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="Request" type="{http://www.egiz.gv.at/stal}RequestType" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="sessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "GetNextRequestResponseType", propOrder = { - "request" -}) -public class GetNextRequestResponseType { - - @XmlElement(name = "Request") - protected List request; - @XmlAttribute - protected String sessionId; - - /** - * Gets the value of the request property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the request property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getRequest().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link STALRequest } - * - * - */ - public List getRequest() { - if (request == null) { - request = new ArrayList(); - } - return this.request; - } - - /** - * Gets the value of the sessionId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSessionId() { - return sessionId; - } - - /** - * Sets the value of the sessionId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSessionId(String value) { - this.sessionId = value; - } - -} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/GetNextRequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/GetNextRequestType.java deleted file mode 100644 index 410f1d8d..00000000 --- a/STALService/src/main/java/at/gv/egiz/stal/service/GetNextRequestType.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.service; - -import at.gv.egiz.stal.STALResponse; -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for GetNextRequestType complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="GetNextRequestType">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <sequence>
- *         <element name="Response" type="{http://www.egiz.gv.at/stal}ResponseType" maxOccurs="unbounded" minOccurs="0"/>
- *       </sequence>
- *       <attribute name="sessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "GetNextRequestType", propOrder = { - "response" -}) -public class GetNextRequestType { - - @XmlElement(name = "Response") - protected List response; - @XmlAttribute - protected String sessionId; - - /** - * Gets the value of the response property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the response property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getResponse().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link STALResponse } - * - * - */ - public List getResponse() { - if (response == null) { - response = new ArrayList(); - } - return this.response; - } - - /** - * Gets the value of the sessionId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getSessionId() { - return sessionId; - } - - /** - * Sets the value of the sessionId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setSessionId(String value) { - this.sessionId = value; - } - -} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/ObjectFactory.java b/STALService/src/main/java/at/gv/egiz/stal/service/ObjectFactory.java deleted file mode 100644 index 11ad1101..00000000 --- a/STALService/src/main/java/at/gv/egiz/stal/service/ObjectFactory.java +++ /dev/null @@ -1,212 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.service; - - -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.InfoboxReadRequest; -import at.gv.egiz.stal.InfoboxReadResponse; -import at.gv.egiz.stal.QuitRequest; -import at.gv.egiz.stal.SignRequest; -import at.gv.egiz.stal.SignResponse; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlElementDecl; -import javax.xml.bind.annotation.XmlRegistry; -import javax.xml.namespace.QName; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the at.gv.egiz.stal package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - private final static QName _GetHashDataInputFault_QNAME = new QName("http://www.egiz.gv.at/stal", "GetHashDataInputFault"); - private final static QName _GetHashDataInput_QNAME = new QName("http://www.egiz.gv.at/stal", "GetHashDataInput"); - private final static QName _GetNextRequestResponse_QNAME = new QName("http://www.egiz.gv.at/stal", "GetNextRequestResponse"); - private final static QName _GetHashDataInputResponse_QNAME = new QName("http://www.egiz.gv.at/stal", "GetHashDataInputResponse"); - private final static QName _GetNextRequest_QNAME = new QName("http://www.egiz.gv.at/stal", "GetNextRequest"); - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: at.gv.egiz.stal - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link GetNextRequestType } - * - */ - public GetNextRequestType createGetNextRequestType() { - return new GetNextRequestType(); - } - - /** - * Create an instance of {@link SignRequest } - * - */ - public SignRequest createSignRequest() { - return new SignRequest(); - } - - /** - * Create an instance of {@link GetHashDataInputResponseType } - * - */ - public GetHashDataInputResponseType createGetHashDataInputResponseType() { - return new GetHashDataInputResponseType(); - } - - /** - * Create an instance of {@link InfoboxReadResponse } - * - */ - public InfoboxReadResponse createInfoboxReadResponse() { - return new InfoboxReadResponse(); - } - - /** - * Create an instance of {@link ErrorResponse } - * - */ - public ErrorResponse createErrorResponse() { - return new ErrorResponse(); - } - - /** - * Create an instance of {@link GetHashDataInputFaultType } - * - */ - public GetHashDataInputFaultType createGetHashDataInputFaultType() { - return new GetHashDataInputFaultType(); - } - - /** - * Create an instance of {@link GetHashDataInputType.Reference } - * - */ - public GetHashDataInputType.Reference createGetHashDataInputTypeReference() { - return new GetHashDataInputType.Reference(); - } - - /** - * Create an instance of {@link InfoboxReadRequest } - * - */ - public InfoboxReadRequest createInfoboxReadRequest() { - return new InfoboxReadRequest(); - } - - /** - * Create an instance of {@link SignResponse } - * - */ - public SignResponse createSignResponse() { - return new SignResponse(); - } - - /** - * Create an instance of {@link GetNextRequestResponseType } - * - */ - public GetNextRequestResponseType createGetNextRequestResponseType() { - return new GetNextRequestResponseType(); - } - - /** - * Create an instance of {@link GetHashDataInputType } - * - */ - public GetHashDataInputType createGetHashDataInputType() { - return new GetHashDataInputType(); - } - - /** - * Create an instance of {@link QuitRequest } - * - */ - public QuitRequest createQuitRequest() { - return new QuitRequest(); - } - - /** - * Create an instance of {@link GetHashDataInputResponseType.Reference } - * - */ - public GetHashDataInputResponseType.Reference createGetHashDataInputResponseTypeReference() { - return new GetHashDataInputResponseType.Reference(); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link GetHashDataInputFaultType }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetHashDataInputFault") - public JAXBElement createGetHashDataInputFault(GetHashDataInputFaultType value) { - return new JAXBElement(_GetHashDataInputFault_QNAME, GetHashDataInputFaultType.class, null, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link GetHashDataInputType }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetHashDataInput") - public JAXBElement createGetHashDataInput(GetHashDataInputType value) { - return new JAXBElement(_GetHashDataInput_QNAME, GetHashDataInputType.class, null, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link GetNextRequestResponseType }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetNextRequestResponse") - public JAXBElement createGetNextRequestResponse(GetNextRequestResponseType value) { - return new JAXBElement(_GetNextRequestResponse_QNAME, GetNextRequestResponseType.class, null, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link GetHashDataInputResponseType }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetHashDataInputResponse") - public JAXBElement createGetHashDataInputResponse(GetHashDataInputResponseType value) { - return new JAXBElement(_GetHashDataInputResponse_QNAME, GetHashDataInputResponseType.class, null, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link GetNextRequestType }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetNextRequest") - public JAXBElement createGetNextRequest(GetNextRequestType value) { - return new JAXBElement(_GetNextRequest_QNAME, GetNextRequestType.class, null, value); - } - -} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/STALPortType.java b/STALService/src/main/java/at/gv/egiz/stal/service/STALPortType.java index 8d1f9f9c..6ac6b10a 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/STALPortType.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/STALPortType.java @@ -1,19 +1,3 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.service; @@ -22,28 +6,42 @@ import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; -import javax.xml.bind.annotation.XmlSeeAlso; +import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputType; +import at.gv.egiz.stal.service.types.GetNextRequestResponseType; +import at.gv.egiz.stal.service.types.GetNextRequestType; + /** * This class was generated by the JAX-WS RI. * JAX-WS RI 2.1.3-b02- - * Generated source version: 2.1 + * Generated source version: 2.0 * */ @WebService(name = "STALPortType", targetNamespace = "http://www.egiz.gv.at/wsdl/stal") @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) -@XmlSeeAlso({ - ObjectFactory.class -}) public interface STALPortType { + /** + * Initial connection, get the first request. + * + * @param sessionId + * @return + * returns at.gv.egiz.stal.service.types.GetNextRequestResponseType + */ + @WebMethod + @WebResult(name = "GetNextRequestResponse", targetNamespace = "http://www.egiz.gv.at/stal", partName = "part1") + public GetNextRequestResponseType connect( + @WebParam(name = "SessionId", targetNamespace = "http://www.egiz.gv.at/stal", partName = "part1") + String sessionId); + /** * Fetch the next request. * * @param request * @return - * returns at.gv.egiz.stal.GetNextRequestResponseType + * returns at.gv.egiz.stal.service.types.GetNextRequestResponseType */ @WebMethod(operationName = "nextRequest") @WebResult(name = "GetNextRequestResponse", targetNamespace = "http://www.egiz.gv.at/stal", partName = "part1") @@ -56,7 +54,7 @@ public interface STALPortType { * * @param request * @return - * returns at.gv.egiz.stal.GetHashDataInputResponseType + * returns at.gv.egiz.stal.service.types.GetHashDataInputResponseType * @throws GetHashDataInputFault */ @WebMethod diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/STALService.java b/STALService/src/main/java/at/gv/egiz/stal/service/STALService.java index 7023b02a..d4b58af9 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/STALService.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/STALService.java @@ -1,36 +1,18 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.service; -import java.net.MalformedURLException; import java.net.URL; import java.util.logging.Logger; import javax.xml.namespace.QName; import javax.xml.ws.Service; import javax.xml.ws.WebEndpoint; import javax.xml.ws.WebServiceClient; -import javax.xml.ws.WebServiceFeature; /** * This class was generated by the JAX-WS RI. * JAX-WS RI 2.1.3-b02- - * Generated source version: 2.1 + * Generated source version: 2.0 * */ @WebServiceClient(name = "STALService", targetNamespace = "http://www.egiz.gv.at/wsdl/stal") @@ -54,16 +36,4 @@ public class STALService return super.getPort(new QName("http://www.egiz.gv.at/wsdl/stal", "STALPort"), STALPortType.class); } - /** - * - * @param features - * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features parameter will have their default values. - * @return - * returns STALPortType - */ - @WebEndpoint(name = "STALPort") - public STALPortType getSTALPort(WebServiceFeature... features) { - return super.getPort(new QName("http://www.egiz.gv.at/wsdl/stal", "STALPort"), STALPortType.class, features); - } - } diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/package-info.java b/STALService/src/main/java/at/gv/egiz/stal/service/package-info.java deleted file mode 100644 index eb3e29dd..00000000 --- a/STALService/src/main/java/at/gv/egiz/stal/service/package-info.java +++ /dev/null @@ -1,18 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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. -*/ -@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.egiz.gv.at/stal", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) -package at.gv.egiz.stal.service; diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/ErrorResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/ErrorResponseType.java new file mode 100644 index 00000000..14ae0d39 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/ErrorResponseType.java @@ -0,0 +1,84 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ErrorResponseType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="ErrorResponseType">
+ *   <complexContent>
+ *     <extension base="{http://www.egiz.gv.at/stal}ResponseType">
+ *       <sequence>
+ *         <element name="ErrorCode" type="{http://www.w3.org/2001/XMLSchema}int"/>
+ *         <element name="ErrorMessage" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </extension>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ErrorResponseType", propOrder = { + "errorCode", + "errorMessage" +}) +public class ErrorResponseType + extends ResponseType +{ + + @XmlElement(name = "ErrorCode") + protected int errorCode; + @XmlElement(name = "ErrorMessage", required = true) + protected String errorMessage; + + /** + * Gets the value of the errorCode property. + * + */ + public int getErrorCode() { + return errorCode; + } + + /** + * Sets the value of the errorCode property. + * + */ + public void setErrorCode(int value) { + this.errorCode = value; + } + + /** + * Gets the value of the errorMessage property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * Sets the value of the errorMessage property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setErrorMessage(String value) { + this.errorMessage = value; + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputFaultType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputFaultType.java new file mode 100644 index 00000000..bf9f96ab --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputFaultType.java @@ -0,0 +1,82 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for GetHashDataInputFaultType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="GetHashDataInputFaultType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="ErrorCode" type="{http://www.w3.org/2001/XMLSchema}int"/>
+ *         <element name="ErrorMessage" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "GetHashDataInputFaultType", propOrder = { + "errorCode", + "errorMessage" +}) +public class GetHashDataInputFaultType { + + @XmlElement(name = "ErrorCode") + protected int errorCode; + @XmlElement(name = "ErrorMessage", required = true) + protected String errorMessage; + + /** + * Gets the value of the errorCode property. + * + */ + public int getErrorCode() { + return errorCode; + } + + /** + * Sets the value of the errorCode property. + * + */ + public void setErrorCode(int value) { + this.errorCode = value; + } + + /** + * Gets the value of the errorMessage property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * Sets the value of the errorMessage property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setErrorMessage(String value) { + this.errorMessage = value; + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputResponseType.java new file mode 100644 index 00000000..7536d936 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputResponseType.java @@ -0,0 +1,239 @@ + +package at.gv.egiz.stal.service.types; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + *

Java class for GetHashDataInputResponseType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="GetHashDataInputResponseType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Reference" maxOccurs="unbounded">
+ *           <complexType>
+ *             <simpleContent>
+ *               <extension base="<http://www.w3.org/2001/XMLSchema>base64Binary">
+ *                 <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                 <attribute name="MimeType" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                 <attribute name="Encoding" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *               </extension>
+ *             </simpleContent>
+ *           </complexType>
+ *         </element>
+ *       </sequence>
+ *       <attribute name="SessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "GetHashDataInputResponseType", propOrder = { + "reference" +}) +public class GetHashDataInputResponseType { + + @XmlElement(name = "Reference", required = true) + protected List reference; + @XmlAttribute(name = "SessionId") + protected String sessionId; + + /** + * Gets the value of the reference property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the reference property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getReference().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link GetHashDataInputResponseType.Reference } + * + * + */ + public List getReference() { + if (reference == null) { + reference = new ArrayList(); + } + return this.reference; + } + + /** + * Gets the value of the sessionId property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSessionId() { + return sessionId; + } + + /** + * Sets the value of the sessionId property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSessionId(String value) { + this.sessionId = value; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <simpleContent>
+     *     <extension base="<http://www.w3.org/2001/XMLSchema>base64Binary">
+     *       <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *       <attribute name="MimeType" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *       <attribute name="Encoding" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *     </extension>
+     *   </simpleContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "value" + }) + public static class Reference { + + @XmlValue + protected byte[] value; + @XmlAttribute(name = "ID") + protected String id; + @XmlAttribute(name = "MimeType") + protected String mimeType; + @XmlAttribute(name = "Encoding") + protected String encoding; + + /** + * Gets the value of the value property. + * + * @return + * possible object is + * byte[] + */ + public byte[] getValue() { + return value; + } + + /** + * Sets the value of the value property. + * + * @param value + * allowed object is + * byte[] + */ + public void setValue(byte[] value) { + this.value = ((byte[]) value); + } + + /** + * Gets the value of the id property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getID() { + return id; + } + + /** + * Sets the value of the id property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setID(String value) { + this.id = value; + } + + /** + * Gets the value of the mimeType property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMimeType() { + return mimeType; + } + + /** + * Sets the value of the mimeType property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMimeType(String value) { + this.mimeType = value; + } + + /** + * Gets the value of the encoding property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getEncoding() { + return encoding; + } + + /** + * Sets the value of the encoding property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setEncoding(String value) { + this.encoding = value; + } + + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputType.java new file mode 100644 index 00000000..5309482a --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputType.java @@ -0,0 +1,156 @@ + +package at.gv.egiz.stal.service.types; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for GetHashDataInputType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="GetHashDataInputType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Reference" maxOccurs="unbounded">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *       </sequence>
+ *       <attribute name="SessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "GetHashDataInputType", propOrder = { + "reference" +}) +public class GetHashDataInputType { + + @XmlElement(name = "Reference", required = true) + protected List reference; + @XmlAttribute(name = "SessionId") + protected String sessionId; + + /** + * Gets the value of the reference property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the reference property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getReference().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link GetHashDataInputType.Reference } + * + * + */ + public List getReference() { + if (reference == null) { + reference = new ArrayList(); + } + return this.reference; + } + + /** + * Gets the value of the sessionId property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSessionId() { + return sessionId; + } + + /** + * Sets the value of the sessionId property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSessionId(String value) { + this.sessionId = value; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Reference { + + @XmlAttribute(name = "ID") + protected String id; + + /** + * Gets the value of the id property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getID() { + return id; + } + + /** + * Sets the value of the id property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setID(String value) { + this.id = value; + } + + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestResponseType.java new file mode 100644 index 00000000..6f8204cc --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestResponseType.java @@ -0,0 +1,106 @@ + +package at.gv.egiz.stal.service.types; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for GetNextRequestResponseType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="GetNextRequestResponseType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <choice maxOccurs="unbounded">
+ *         <element name="InfoboxReadRequest" type="{http://www.egiz.gv.at/stal}InfoboxReadRequestType"/>
+ *         <element name="SignRequest" type="{http://www.egiz.gv.at/stal}SignRequestType"/>
+ *         <element name="QuitRequest" type="{http://www.egiz.gv.at/stal}QuitRequestType"/>
+ *       </choice>
+ *       <attribute name="SessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "GetNextRequestResponseType", propOrder = { + "infoboxReadRequestOrSignRequestOrQuitRequest" +}) +public class GetNextRequestResponseType { + + @XmlElements({ + @XmlElement(name = "InfoboxReadRequest", type = InfoboxReadRequestType.class), + @XmlElement(name = "QuitRequest", type = QuitRequestType.class), + @XmlElement(name = "SignRequest", type = SignRequestType.class) + }) + protected List infoboxReadRequestOrSignRequestOrQuitRequest; + @XmlAttribute(name = "SessionId") + protected String sessionId; + + /** + * Gets the value of the infoboxReadRequestOrSignRequestOrQuitRequest property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the infoboxReadRequestOrSignRequestOrQuitRequest property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getInfoboxReadRequestOrSignRequestOrQuitRequest().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link InfoboxReadRequestType } + * {@link QuitRequestType } + * {@link SignRequestType } + * + * + */ + public List getInfoboxReadRequestOrSignRequestOrQuitRequest() { + if (infoboxReadRequestOrSignRequestOrQuitRequest == null) { + infoboxReadRequestOrSignRequestOrQuitRequest = new ArrayList(); + } + return this.infoboxReadRequestOrSignRequestOrQuitRequest; + } + + /** + * Gets the value of the sessionId property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSessionId() { + return sessionId; + } + + /** + * Sets the value of the sessionId property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSessionId(String value) { + this.sessionId = value; + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestType.java new file mode 100644 index 00000000..eab3d40b --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestType.java @@ -0,0 +1,106 @@ + +package at.gv.egiz.stal.service.types; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for GetNextRequestType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="GetNextRequestType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <choice maxOccurs="unbounded">
+ *         <element name="InfoboxReadResponse" type="{http://www.egiz.gv.at/stal}InfoboxReadResponseType"/>
+ *         <element name="SignResponse" type="{http://www.egiz.gv.at/stal}SignResponseType"/>
+ *         <element name="ErrorResponse" type="{http://www.egiz.gv.at/stal}ErrorResponseType"/>
+ *       </choice>
+ *       <attribute name="SessionId" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "GetNextRequestType", propOrder = { + "infoboxReadResponseOrSignResponseOrErrorResponse" +}) +public class GetNextRequestType { + + @XmlElements({ + @XmlElement(name = "SignResponse", type = SignResponseType.class), + @XmlElement(name = "InfoboxReadResponse", type = InfoboxReadResponseType.class), + @XmlElement(name = "ErrorResponse", type = ErrorResponseType.class) + }) + protected List infoboxReadResponseOrSignResponseOrErrorResponse; + @XmlAttribute(name = "SessionId") + protected String sessionId; + + /** + * Gets the value of the infoboxReadResponseOrSignResponseOrErrorResponse property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the infoboxReadResponseOrSignResponseOrErrorResponse property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getInfoboxReadResponseOrSignResponseOrErrorResponse().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SignResponseType } + * {@link InfoboxReadResponseType } + * {@link ErrorResponseType } + * + * + */ + public List getInfoboxReadResponseOrSignResponseOrErrorResponse() { + if (infoboxReadResponseOrSignResponseOrErrorResponse == null) { + infoboxReadResponseOrSignResponseOrErrorResponse = new ArrayList(); + } + return this.infoboxReadResponseOrSignResponseOrErrorResponse; + } + + /** + * Gets the value of the sessionId property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSessionId() { + return sessionId; + } + + /** + * Sets the value of the sessionId property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSessionId(String value) { + this.sessionId = value; + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/InfoboxReadRequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/InfoboxReadRequestType.java new file mode 100644 index 00000000..0ab6f5f3 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/InfoboxReadRequestType.java @@ -0,0 +1,102 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for InfoboxReadRequestType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="InfoboxReadRequestType">
+ *   <complexContent>
+ *     <extension base="{http://www.egiz.gv.at/stal}RequestType">
+ *       <sequence>
+ *         <element name="InfoboxIdentifier">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="Certificates"/>
+ *               <enumeration value="IdentityLink"/>
+ *               <enumeration value="Mandates"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="DomainIdentifier" type="{http://www.w3.org/2001/XMLSchema}anyURI" minOccurs="0"/>
+ *       </sequence>
+ *     </extension>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "InfoboxReadRequestType", propOrder = { + "infoboxIdentifier", + "domainIdentifier" +}) +public class InfoboxReadRequestType + extends RequestType +{ + + @XmlElement(name = "InfoboxIdentifier", required = true) + protected String infoboxIdentifier; + @XmlElement(name = "DomainIdentifier") + @XmlSchemaType(name = "anyURI") + protected String domainIdentifier; + + /** + * Gets the value of the infoboxIdentifier property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getInfoboxIdentifier() { + return infoboxIdentifier; + } + + /** + * Sets the value of the infoboxIdentifier property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setInfoboxIdentifier(String value) { + this.infoboxIdentifier = value; + } + + /** + * Gets the value of the domainIdentifier property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDomainIdentifier() { + return domainIdentifier; + } + + /** + * Sets the value of the domainIdentifier property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDomainIdentifier(String value) { + this.domainIdentifier = value; + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/InfoboxReadResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/InfoboxReadResponseType.java new file mode 100644 index 00000000..1d88737d --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/InfoboxReadResponseType.java @@ -0,0 +1,62 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for InfoboxReadResponseType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="InfoboxReadResponseType">
+ *   <complexContent>
+ *     <extension base="{http://www.egiz.gv.at/stal}ResponseType">
+ *       <sequence>
+ *         <element name="InfoboxValue" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ *       </sequence>
+ *     </extension>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "InfoboxReadResponseType", propOrder = { + "infoboxValue" +}) +public class InfoboxReadResponseType + extends ResponseType +{ + + @XmlElement(name = "InfoboxValue", required = true) + protected byte[] infoboxValue; + + /** + * Gets the value of the infoboxValue property. + * + * @return + * possible object is + * byte[] + */ + public byte[] getInfoboxValue() { + return infoboxValue; + } + + /** + * Sets the value of the infoboxValue property. + * + * @param value + * allowed object is + * byte[] + */ + public void setInfoboxValue(byte[] value) { + this.infoboxValue = ((byte[]) value); + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/ObjectFactory.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/ObjectFactory.java new file mode 100644 index 00000000..d485f1e1 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/ObjectFactory.java @@ -0,0 +1,199 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElementDecl; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the at.gv.egiz.stal.service.types package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + private final static QName _GetHashDataInputFault_QNAME = new QName("http://www.egiz.gv.at/stal", "GetHashDataInputFault"); + private final static QName _GetHashDataInput_QNAME = new QName("http://www.egiz.gv.at/stal", "GetHashDataInput"); + private final static QName _GetNextRequestResponse_QNAME = new QName("http://www.egiz.gv.at/stal", "GetNextRequestResponse"); + private final static QName _GetHashDataInputResponse_QNAME = new QName("http://www.egiz.gv.at/stal", "GetHashDataInputResponse"); + private final static QName _GetNextRequest_QNAME = new QName("http://www.egiz.gv.at/stal", "GetNextRequest"); + private final static QName _SessionId_QNAME = new QName("http://www.egiz.gv.at/stal", "SessionId"); + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: at.gv.egiz.stal.service.types + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link GetNextRequestType } + * + */ + public GetNextRequestType createGetNextRequestType() { + return new GetNextRequestType(); + } + + /** + * Create an instance of {@link InfoboxReadRequestType } + * + */ + public InfoboxReadRequestType createInfoboxReadRequestType() { + return new InfoboxReadRequestType(); + } + + /** + * Create an instance of {@link GetHashDataInputResponseType.Reference } + * + */ + public GetHashDataInputResponseType.Reference createGetHashDataInputResponseTypeReference() { + return new GetHashDataInputResponseType.Reference(); + } + + /** + * Create an instance of {@link ErrorResponseType } + * + */ + public ErrorResponseType createErrorResponseType() { + return new ErrorResponseType(); + } + + /** + * Create an instance of {@link GetHashDataInputType } + * + */ + public GetHashDataInputType createGetHashDataInputType() { + return new GetHashDataInputType(); + } + + /** + * Create an instance of {@link SignRequestType } + * + */ + public SignRequestType createSignRequestType() { + return new SignRequestType(); + } + + /** + * Create an instance of {@link GetHashDataInputFaultType } + * + */ + public GetHashDataInputFaultType createGetHashDataInputFaultType() { + return new GetHashDataInputFaultType(); + } + + /** + * Create an instance of {@link SignResponseType } + * + */ + public SignResponseType createSignResponseType() { + return new SignResponseType(); + } + + /** + * Create an instance of {@link GetHashDataInputType.Reference } + * + */ + public GetHashDataInputType.Reference createGetHashDataInputTypeReference() { + return new GetHashDataInputType.Reference(); + } + + /** + * Create an instance of {@link GetHashDataInputResponseType } + * + */ + public GetHashDataInputResponseType createGetHashDataInputResponseType() { + return new GetHashDataInputResponseType(); + } + + /** + * Create an instance of {@link InfoboxReadResponseType } + * + */ + public InfoboxReadResponseType createInfoboxReadResponseType() { + return new InfoboxReadResponseType(); + } + + /** + * Create an instance of {@link QuitRequestType } + * + */ + public QuitRequestType createQuitRequestType() { + return new QuitRequestType(); + } + + /** + * Create an instance of {@link GetNextRequestResponseType } + * + */ + public GetNextRequestResponseType createGetNextRequestResponseType() { + return new GetNextRequestResponseType(); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link GetHashDataInputFaultType }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetHashDataInputFault") + public JAXBElement createGetHashDataInputFault(GetHashDataInputFaultType value) { + return new JAXBElement(_GetHashDataInputFault_QNAME, GetHashDataInputFaultType.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link GetHashDataInputType }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetHashDataInput") + public JAXBElement createGetHashDataInput(GetHashDataInputType value) { + return new JAXBElement(_GetHashDataInput_QNAME, GetHashDataInputType.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link GetNextRequestResponseType }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetNextRequestResponse") + public JAXBElement createGetNextRequestResponse(GetNextRequestResponseType value) { + return new JAXBElement(_GetNextRequestResponse_QNAME, GetNextRequestResponseType.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link GetHashDataInputResponseType }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetHashDataInputResponse") + public JAXBElement createGetHashDataInputResponse(GetHashDataInputResponseType value) { + return new JAXBElement(_GetHashDataInputResponse_QNAME, GetHashDataInputResponseType.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link GetNextRequestType }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "GetNextRequest") + public JAXBElement createGetNextRequest(GetNextRequestType value) { + return new JAXBElement(_GetNextRequest_QNAME, GetNextRequestType.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "SessionId") + public JAXBElement createSessionId(String value) { + return new JAXBElement(_SessionId_QNAME, String.class, null, value); + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/QuitRequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/QuitRequestType.java new file mode 100644 index 00000000..7dc4197f --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/QuitRequestType.java @@ -0,0 +1,32 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for QuitRequestType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="QuitRequestType">
+ *   <complexContent>
+ *     <extension base="{http://www.egiz.gv.at/stal}RequestType">
+ *     </extension>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "QuitRequestType") +public class QuitRequestType + extends RequestType +{ + + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/RequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/RequestType.java new file mode 100644 index 00000000..32b7894f --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/RequestType.java @@ -0,0 +1,30 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for RequestType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="RequestType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "RequestType") +public abstract class RequestType { + + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/ResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/ResponseType.java new file mode 100644 index 00000000..c94bcbe8 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/ResponseType.java @@ -0,0 +1,30 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ResponseType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="ResponseType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ResponseType") +public abstract class ResponseType { + + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/SignRequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/SignRequestType.java new file mode 100644 index 00000000..09e30967 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/SignRequestType.java @@ -0,0 +1,97 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for SignRequestType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="SignRequestType">
+ *   <complexContent>
+ *     <extension base="{http://www.egiz.gv.at/stal}RequestType">
+ *       <sequence>
+ *         <element name="KeyIdentifier">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="SecureSignatureKeypair"/>
+ *               <enumeration value="CertifiedKeypair"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="SignedInfo" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ *       </sequence>
+ *     </extension>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SignRequestType", propOrder = { + "keyIdentifier", + "signedInfo" +}) +public class SignRequestType + extends RequestType +{ + + @XmlElement(name = "KeyIdentifier", required = true) + protected String keyIdentifier; + @XmlElement(name = "SignedInfo", required = true) + protected byte[] signedInfo; + + /** + * Gets the value of the keyIdentifier property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getKeyIdentifier() { + return keyIdentifier; + } + + /** + * Sets the value of the keyIdentifier property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setKeyIdentifier(String value) { + this.keyIdentifier = value; + } + + /** + * Gets the value of the signedInfo property. + * + * @return + * possible object is + * byte[] + */ + public byte[] getSignedInfo() { + return signedInfo; + } + + /** + * Sets the value of the signedInfo property. + * + * @param value + * allowed object is + * byte[] + */ + public void setSignedInfo(byte[] value) { + this.signedInfo = ((byte[]) value); + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/SignResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/SignResponseType.java new file mode 100644 index 00000000..a33fb34c --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/SignResponseType.java @@ -0,0 +1,62 @@ + +package at.gv.egiz.stal.service.types; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for SignResponseType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="SignResponseType">
+ *   <complexContent>
+ *     <extension base="{http://www.egiz.gv.at/stal}ResponseType">
+ *       <sequence>
+ *         <element name="SignatureValue" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ *       </sequence>
+ *     </extension>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SignResponseType", propOrder = { + "signatureValue" +}) +public class SignResponseType + extends ResponseType +{ + + @XmlElement(name = "SignatureValue", required = true) + protected byte[] signatureValue; + + /** + * Gets the value of the signatureValue property. + * + * @return + * possible object is + * byte[] + */ + public byte[] getSignatureValue() { + return signatureValue; + } + + /** + * Sets the value of the signatureValue property. + * + * @param value + * allowed object is + * byte[] + */ + public void setSignatureValue(byte[] value) { + this.signatureValue = ((byte[]) value); + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/package-info.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/package-info.java new file mode 100644 index 00000000..3328fdc0 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/package-info.java @@ -0,0 +1,2 @@ +@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.egiz.gv.at/stal", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +package at.gv.egiz.stal.service.types; diff --git a/STALService/src/main/java/at/gv/egiz/stal/util/STALTranslator.java b/STALService/src/main/java/at/gv/egiz/stal/util/STALTranslator.java new file mode 100644 index 00000000..b8681084 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/util/STALTranslator.java @@ -0,0 +1,109 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package at.gv.egiz.stal.util; + +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.InfoboxReadResponse; +import at.gv.egiz.stal.QuitRequest; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.SignResponse; +import at.gv.egiz.stal.service.types.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author clemens + */ +public class STALTranslator { + + protected static final Log log = LogFactory.getLog(STALTranslator.class); + + public static List translateRequests(List requests) { + List stalRequests = new ArrayList(requests.size()); + for (RequestType request : requests) { + if (request instanceof InfoboxReadRequestType) { + InfoboxReadRequest stalReq = new InfoboxReadRequest(); + stalReq.setDomainIdentifier(((InfoboxReadRequestType) request).getDomainIdentifier()); + stalReq.setInfoboxIdentifier(((InfoboxReadRequestType) request).getInfoboxIdentifier()); + stalRequests.add(stalReq); + } else if (request instanceof SignRequestType) { + SignRequest stalReq = new SignRequest(); + stalReq.setKeyIdentifier(((SignRequestType) request).getKeyIdentifier()); + stalReq.setSignedInfo(((SignRequestType) request).getSignedInfo()); + stalRequests.add(stalReq); + } else if (request instanceof QuitRequestType) { + stalRequests.add(new QuitRequest()); + } else { + log.error("unknown STALService request type: " + request.getClass()); + stalRequests = Collections.singletonList((STALRequest) new QuitRequest()); + break; + } + } + return stalRequests; + } + + public static List fromSTAL(List stalResponses) { + List responses = new ArrayList(stalResponses.size()); + for (STALResponse stalResp : stalResponses) { + if (stalResp instanceof InfoboxReadResponse) { + InfoboxReadResponseType resp = new InfoboxReadResponseType(); + resp.setInfoboxValue(((InfoboxReadResponse) stalResp).getInfoboxValue()); + responses.add(resp); + } else if (stalResp instanceof SignResponse) { + SignResponseType resp = new SignResponseType(); + resp.setSignatureValue(((SignResponse) stalResp).getSignatureValue()); + responses.add(resp); + } else if (stalResp instanceof ErrorResponse) { + ErrorResponseType resp = new ErrorResponseType(); + resp.setErrorCode(((ErrorResponse) stalResp).getErrorCode()); + resp.setErrorMessage(((ErrorResponse) stalResp).getErrorMessage()); + responses.add(resp); + } else { + log.error("unknown STAL response type: " + stalResp.getClass()); + ErrorResponseType resp = new ErrorResponseType(); + resp.setErrorCode(4000); + resp.setErrorMessage("unknown STAL response type: " + stalResp.getClass()); + responses = Collections.singletonList((ResponseType) resp); + break; + } + } + return responses; + } + + public static List toSTAL(List responses) { + List stalResponses = new ArrayList(responses.size()); + for (ResponseType resp : responses) { + if (resp instanceof InfoboxReadResponseType) { + InfoboxReadResponse stalResp = new InfoboxReadResponse(); + stalResp.setInfoboxValue(((InfoboxReadResponseType) resp).getInfoboxValue()); + stalResponses.add(stalResp); + } else if (resp instanceof SignResponseType) { + SignResponse stalResp = new SignResponse(); + stalResp.setSignatureValue(((SignResponseType) resp).getSignatureValue()); + stalResponses.add(stalResp); + } else if (resp instanceof ErrorResponseType) { + ErrorResponse stalResp = new ErrorResponse(); + stalResp.setErrorCode(((ErrorResponseType) resp).getErrorCode()); + stalResp.setErrorMessage(((ErrorResponseType) resp).getErrorMessage()); + stalResponses.add(stalResp); + } else { + log.error("unknown STALService response type: " + resp.getClass()); + ErrorResponse stalResp = new ErrorResponse(); + stalResp.setErrorCode(4000); + stalResp.setErrorMessage("unknown STALService response type: " + resp.getClass()); + stalResponses = Collections.singletonList((STALResponse) stalResp); + break; + } + } + return stalResponses; + } +} diff --git a/pom.xml b/pom.xml index 3438e596..dbe2812e 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,12 @@ - - 4.0.0 - at.gv.egiz - bku - pom - 1.0-SNAPSHOT - BKU - http://bku.egiz.gv.at + + 4.0.0 + at.gv.egiz + bku + pom + 1.0-SNAPSHOT + BKU + http://bku.egiz.gv.at utils bkucommon @@ -18,7 +18,7 @@ smccSTAL STALService BKUCommonGUI - BKUViewer + BKUViewer @@ -43,74 +43,74 @@ E-Government Innovation Center (EGIZ) http://www.egiz.gv.at - - - - - - maven-compiler-plugin - org.apache.maven.plugins - 2.0.2 - - - 1.6 - 1.6 - true - true - - - - maven-assembly-plugin - org.apache.maven.plugins - 2.2-beta-2 - - - maven-dependency-plugin - org.apache.maven.plugins - 2.0 - - - maven-jaxb2-plugin - org.jvnet.jaxb2.maven2 - 0.6.0 - - - jaxws-maven-plugin - org.codehaus.mojo - 1.10 - - - - - - maven-assembly-plugin - - - ${basedir}/src/main/assemblies/assembly-test.xml - - - - - - + + + + + + maven-compiler-plugin + org.apache.maven.plugins + 2.0.2 + + + 1.6 + 1.6 + true + true + + + + maven-assembly-plugin + org.apache.maven.plugins + 2.2-beta-2 + + + maven-dependency-plugin + org.apache.maven.plugins + 2.0 + + + + jaxws-maven-plugin + org.codehaus.mojo + 1.10 + + + + + + maven-assembly-plugin + + + ${basedir}/src/main/assemblies/assembly-test.xml + + + + + + @@ -129,39 +129,39 @@ http://download.java.net/maven/1/ legacy - - - - log4j - log4j - runtime - - - junit - junit - test - - - - - - log4j - log4j - 1.2.12 - runtime - - - commons-logging - commons-logging - 1.1.1 - compile - - - junit - junit - 4.4 - test - + + + + log4j + log4j + runtime + + + junit + junit + test + + + + + + log4j + log4j + 1.2.12 + runtime + + + commons-logging + commons-logging + 1.1.1 + compile + + + junit + junit + 4.4 + test + xerces xercesImpl @@ -172,39 +172,39 @@ xalan 2.7.0 - - iaik - iaik_jce_full_signed - 3.16 - compile - - - iaik - iaik_jce_me4se - 3.04 - - - iaik - iaik_ecc_signed - 2.15 - - - iaik - iaik_xsect - 1.14 - - - commons-fileupload - commons-fileupload - 1.2.1 - compile - - - commons-httpclient - commons-httpclient - 3.1 - compile - - - + + iaik + iaik_jce_full_signed + 3.16 + compile + + + iaik + iaik_jce_me4se + 3.04 + + + iaik + iaik_ecc_signed + 2.15 + + + iaik + iaik_xsect + 1.14 + + + commons-fileupload + commons-fileupload + 1.2.1 + compile + + + commons-httpclient + commons-httpclient + 3.1 + compile + + + \ No newline at end of file diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index f3b94078..8ee70f1a 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -65,7 +65,7 @@ public abstract class AbstractSMCCSTAL implements STAL { List responseList = new ArrayList(requestList .size()); for (STALRequest request : requestList) { - log.info("Processing: " + request); + log.info("Processing: " + request.getClass()); SMCCSTALRequestHandler handler = null; handler = handlerMap.get(request.getClass().getSimpleName()); if (handler != null) { @@ -78,7 +78,10 @@ public abstract class AbstractSMCCSTAL implements STAL { try { handler = handler.newInstance(); handler.init(signatureCard, getGUI()); - responseList.add(handler.handleRequest(request)); + STALResponse response = handler.handleRequest(request); + if (response != null) { + responseList.add(response); + } } catch (Exception e) { log.info("Error while handling STAL request:" + e); responseList.add(new ErrorResponse(6000)); -- cgit v1.2.3 From 8ccd9ab69dc74762567930f4c576a359502f1071 Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 30 Sep 2008 16:37:59 +0000 Subject: showErrorDialog l10n git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@77 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/bku/online/applet/BKUWorker.java | 10 +++--- .../src/main/java/at/gv/egiz/bku/gui/BKUGUI.java | 41 +++++++++++++--------- .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 14 ++++++-- .../at/gv/egiz/bku/gui/Messages.properties | 11 +++++- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 33 +++++++++++------ .../at/gv/egiz/bku/local/stal/BKUGuiProxy.java | 8 ++--- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 7 ++-- 7 files changed, 81 insertions(+), 43 deletions(-) (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java index a87b04c4..12eb9d00 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java @@ -126,7 +126,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, log.fatal("Failed to call STAL service.", e); actionCommandList.clear(); actionCommandList.add("ok"); - gui.showErrorDialog(errorMessages.getString("failed.WS")); + gui.showErrorDialog(BKUGUIFacade.ERR_SERVICE_UNREACHABLE, new Object[] {e.getMessage()}); try { waitForAction(); } catch (InterruptedException e1) { @@ -204,7 +204,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, log.info("Done " + Thread.currentThread().getName()); } catch (Exception ex) { log.error(ex.getMessage(), ex); - gui.showErrorDialog("Sorry, an internal error occured: " + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {ex.getMessage()}); try { waitForAction(); } catch (InterruptedException e) { @@ -279,8 +279,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, case SMCCHelper.PC_SC_NOT_SUPPORTED: actionCommandList.clear(); actionCommandList.add("ok"); - gui.showErrorDialog(errorMessages.getString("nopcscsupport"), this, - "ok"); + gui.showErrorDialog(BKUGUIFacade.ERR_NO_PCSC, null, this, "ok"); try { waitForAction(); } catch (InterruptedException e) { @@ -290,8 +289,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, case SMCCHelper.TERMINAL_NOT_PRESENT: actionCommandList.clear(); actionCommandList.add("ok"); - gui.showErrorDialog(errorMessages.getString("nocardterminal"), this, - "ok"); + gui.showErrorDialog(BKUGUIFacade.ERR_NO_CARDTERMINAL,null,this,"ok"); try { waitForAction(); } catch (InterruptedException e) { diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java index 749207ee..b09669b8 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java @@ -41,6 +41,8 @@ import java.util.List; import java.util.Locale; import java.util.ResourceBundle; import java.util.StringTokenizer; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.GroupLayout; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -94,7 +96,7 @@ public class BKUGUI implements BKUGUIFacade { private static final String MESSAGE_OVERWRITE = "message.overwrite"; private static final String LABEL_PIN = "label.pin"; private static final String LABEL_PINSIZE = "label.pinsize"; - private static final String ERROR_NO_HASHDATA = "error.no.hashdata"; +// private static final String ERROR_NO_HASHDATA = "error.no.hashdata"; private static final String BUTTON_OK = "button.ok"; private static final String BUTTON_CANCEL = "button.cancel"; @@ -798,7 +800,7 @@ public class BKUGUI implements BKUGUIFacade { } @Override - public void showErrorDialog(final String errorMsg, final ActionListener okListener, final String okCommand) { + public void showErrorDialog(final String errorMsgKey, final Object[] errorMsgParams, final ActionListener okListener, final String okCommand) { log.debug("scheduling error dialog"); @@ -815,9 +817,12 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_ERROR)); // titleLabel.setForeground(defaultForground); + String errorMsgPattern = messages.getString(errorMsgKey); + String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); + JLabel errorMsgLabel = new JLabel(); errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - errorMsgLabel.setText("" + errorMsg + ""); + errorMsgLabel.setText(errorMsg); errorMsgLabel.setForeground(ERROR_COLOR); GroupLayout mainPanelLayout = new GroupLayout(mainPanel); @@ -860,7 +865,7 @@ public class BKUGUI implements BKUGUIFacade { } @Override - public void showErrorDialog(final String errorMsg) { + public void showErrorDialog(final String errorMsgKey, final Object[] errorMsgParams) { log.debug("scheduling error dialog"); @@ -877,10 +882,13 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_ERROR)); // titleLabel.setForeground(defaultForground); - JLabel errorMsgLabel = new JLabel(); - errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - errorMsgLabel.setText("" + errorMsg + ""); - errorMsgLabel.setForeground(ERROR_COLOR); + String errorMsgPattern = messages.getString(errorMsgKey); + String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); + + JLabel errorMsgLabel = new JLabel(); + errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + errorMsgLabel.setText(errorMsg); + errorMsgLabel.setForeground(ERROR_COLOR); GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); @@ -955,7 +963,7 @@ public class BKUGUI implements BKUGUIFacade { public void showHashDataInputDialog(final List signedReferences, final ActionListener okListener, final String okCommand) { if (signedReferences == null) { - showErrorDialog(messages.getString(ERROR_NO_HASHDATA), okListener, okCommand); + showErrorDialog(messages.getString(ERR_NO_HASHDATA), new Object[] {"No SignedReferences provided"}, okListener, okCommand); } if (signedReferences.size() == 1) { @@ -971,11 +979,12 @@ public class BKUGUI implements BKUGUIFacade { showSaveHashDataInputDialog(signedReferences, okListener, okCommand); } }; - String hashDataText = getText(signedReferences.get(0)); - if (hashDataText != null) { + + try { + String hashDataText = getText(signedReferences.get(0)); showPlainTextHashDataInputDialog(hashDataText, saveHashDataListener, "save", okListener, okCommand); - } else { - showErrorDialog(messages.getString(ERROR_NO_HASHDATA), okListener, okCommand); + } catch (IOException ex) { + showErrorDialog(messages.getString(ERR_NO_HASHDATA), new Object[] {ex.getMessage()}, okListener, okCommand); } } else { @@ -1300,7 +1309,7 @@ public class BKUGUI implements BKUGUIFacade { bos.close(); } catch (IOException ex) { log.error("Failed to write HashDataInput to file " + file + ": " + ex.getMessage()); - showErrorDialog("Failed to write signed reference to file: " + ex.getMessage(), null, null); + showErrorDialog(ERR_WRITE_HASHDATA, new Object[] {ex.getMessage()}, null, null); ex.printStackTrace(); } finally { try { @@ -1316,7 +1325,7 @@ public class BKUGUI implements BKUGUIFacade { }); } - private static String getText(HashDataInput hdi) { + private static String getText(HashDataInput hdi) throws IOException { ByteArrayOutputStream baos = null; try { InputStream hashDataIS = hdi.getHashDataInput(); @@ -1338,7 +1347,7 @@ public class BKUGUI implements BKUGUIFacade { } } catch (IOException ex) { log.error("Failed to read HashDataInput for reference " + hdi.getReferenceId() + ": " + ex.getMessage()); - return null; + throw ex; } finally { try { baos.close(); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index f4b6325d..32eb4c3e 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -23,7 +23,15 @@ import java.awt.event.ActionListener; import java.util.List; public interface BKUGUIFacade { - + + public static final String ERR_UNKNOWN = "error.unknown"; + public static final String ERR_SERVICE_UNREACHABLE = "error.ws.unreachable"; + public static final String ERR_NO_PCSC = "error.pcsc"; + public static final String ERR_NO_CARDTERMINAL = "error.cardterminal"; + public static final String ERR_NO_HASHDATA = "error.no.hashdata"; + public static final String ERR_WRITE_HASHDATA = "error.write.hashdata"; + public static final String ERR_INVALID_HASH = "error.invalid.hash"; + public void init(Container contentPane, String localeString); public void showWelcomeDialog(); @@ -55,7 +63,7 @@ public interface BKUGUIFacade { // public void showPlainTextHashDataInputDialog(String text, ActionListener saveListener, String saveCommand, ActionListener cancelListener, String cancelCommand); - public void showErrorDialog(String errorMsg, ActionListener okListener, String actionCommand); + public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, String actionCommand); - public void showErrorDialog(String errorMsg); + public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams); } diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index a329ba86..79e23859 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -35,7 +35,6 @@ message.retries=Noch {0} Versuche message.overwrite=M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben? label.pin={0}: label.pinsize=({0} stellig) -error.no.hashdata=Keine Signaturdaten verf\u00FCgbar button.ok=OK button.cancel=Abbrechen button.back=Zur\u00FCck @@ -48,3 +47,13 @@ mimetype.desc.txt=Textdateien (.txt) mimetype.desc.pdf=Adobe PDF-Dateien (.pdf) mimetype.desc.bin=Bin\u00E4rdateien (.bin) save.hashdatainput.prefix=Signaturdaten + +# Error Messages +error.no.hashdata=Keine Signaturdaten verf\u00FCgbar: {0} +error.write.hashdata=Die Signaturdaten konnten nicht gespeichert werden: {0} +error.invalid.hash=Die Signaturdaten sind ung\u00FCltig: {0} +error.ws.unreachable=Das Web-Service ist nicht erreichbar: {0} +error.pcsc=Java(TM) scheint keine PC/SC Schnittstelle f\u00FCr den Smartcard-Zugriff zur Verf\u00FCgung zu stellen. +error.cardterminal=Es konnte kein Smartcard-Leser gefunden werden.

Entweder ist kein Leser angeschlossen oder kein PC/SC Treiber installiert.

+error.unknown=Leider trat ein Fehler auf: {0} +error.test=Fehler1 {0} - Fehler2 {1} \ No newline at end of file diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index 909da4ad..0641bf58 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -186,13 +186,13 @@ public class BKUGUIWorker implements Runnable { // // Thread.sleep(2000); - gui.showWaitDialog(null); - - Thread.sleep(1000); - - gui.showWaitDialog("test"); - - Thread.sleep(1000); +// gui.showWaitDialog(null); +// +// Thread.sleep(1000); +// +// gui.showWaitDialog("test"); +// +// Thread.sleep(1000); // gui.showInsertCardDialog(cancelListener, "cancel"); @@ -218,11 +218,24 @@ public class BKUGUIWorker implements Runnable { // // Thread.sleep(2000); //// - gui.showErrorDialog("Testfehler occured", null, null); - +// gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {"Testfehler"}, null, null); +// +// Thread.sleep(2000); +// + + gui.showErrorDialog("error.test", new Object[] {"Testfehler", "noch ein TestFehler"}); + Thread.sleep(2000); // - gui.showErrorDialog("Testfehler occured"); + gui.showErrorDialog("error.no.hashdata", null); + + Thread.sleep(2000); +// + gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {"Testfehler"}); + + Thread.sleep(2000); +// + gui.showErrorDialog("error.unknown", null); // gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save"); diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java index c543c8ca..22ab1d6f 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java @@ -65,16 +65,16 @@ public class BKUGuiProxy implements BKUGUIFacade { } @Override - public void showErrorDialog(String errorMsg, ActionListener okListener, + public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, String actionCommand) { showDialog(); - delegate.showErrorDialog(errorMsg, okListener, actionCommand); + delegate.showErrorDialog(errorMsgKey, errorMsgParams, okListener, actionCommand); } @Override - public void showErrorDialog(String errorMsg) { + public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams) { showDialog(); - delegate.showErrorDialog(errorMsg); + delegate.showErrorDialog(errorMsgKey, errorMsgParams); } @Override diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 0b297283..7d994392 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -16,6 +16,7 @@ */ package at.gv.egiz.bku.smccstal; +import at.gv.egiz.bku.gui.BKUGUIFacade; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.security.MessageDigest; @@ -318,15 +319,15 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen gui.showHashDataInputDialog(hashDataInputs, SignRequestHandler.this, "ok"); } catch (DigestException ex) { log.error("Bad digest value: " + ex.getMessage()); - gui.showErrorDialog(ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, new Object[] {ex.getMessage()}); } catch (Exception ex) { //FIXME localize messages log.error("Failed to obtain HashDataInputs: " + ex.getMessage()); - gui.showErrorDialog("Failed to obtain HashDataInputs: " + ex.getMessage(), SignRequestHandler.this, "ok"); + gui.showErrorDialog(BKUGUIFacade.ERR_NO_HASHDATA, new Object[] {ex.getMessage()}, SignRequestHandler.this, "ok"); } } else { //FIXME get all hashdatainputs - gui.showErrorDialog("Failed to obtain HashDataInputs: No dsig:SignedInfo provided.", SignRequestHandler.this, "ok"); + gui.showErrorDialog(BKUGUIFacade.ERR_NO_HASHDATA, new Object[] {"No dsig:SignedInfo provided"}, SignRequestHandler.this, "ok"); } } else if (actionCommand.equals("sign")) { return new String(gui.getPin()); -- cgit v1.2.3 From 144c0133dcb107b30799a310ba51460d6479358d Mon Sep 17 00:00:00 2001 From: wbauer Date: Thu, 9 Oct 2008 13:14:45 +0000 Subject: Added an smcc retry function to make smartcard access more robust. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@89 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../bku/online/webapp/HashDataInputServlet.java | 13 ++- BKUOnline/src/main/webapp/finanzonline/iframe.html | 2 +- BKUOnline/src/main/webapp/multiHashDataInput.html | 37 +++++++ .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 111 +++++++++++++-------- 4 files changed, 122 insertions(+), 41 deletions(-) create mode 100644 BKUOnline/src/main/webapp/multiHashDataInput.html (limited to 'smccSTAL/src') diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/HashDataInputServlet.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/HashDataInputServlet.java index 59766586..df338c4a 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/HashDataInputServlet.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/HashDataInputServlet.java @@ -5,11 +5,15 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; +import java.net.MalformedURLException; +import java.net.URL; import java.util.List; +import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -17,10 +21,12 @@ import org.apache.commons.logging.LogFactory; import at.gv.egiz.bku.binding.BindingProcessor; import at.gv.egiz.bku.binding.Id; import at.gv.egiz.bku.binding.IdFactory; +import at.gv.egiz.bku.online.applet.BKUApplet; import at.gv.egiz.bku.slexceptions.SLRuntimeException; import at.gv.egiz.bku.utils.StreamUtil; import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.service.STALService; import at.gv.egiz.stal.service.impl.STALRequestBroker; import at.gv.egiz.stal.service.impl.STALRequestBrokerImpl; import at.gv.egiz.stal.service.impl.STALServiceImpl; @@ -30,6 +36,7 @@ public class HashDataInputServlet extends SpringBKUServlet { private static Log log = LogFactory.getLog(HashDataInputServlet.class); public HashDataInputServlet() { + } private STALRequestBroker getSTAL(Id id) { @@ -64,12 +71,16 @@ public class HashDataInputServlet extends SpringBKUServlet { List hdi = rb.getHashDataInput(); log.debug("Got hashdata list with " + hdi.size() + " entries"); String param = req.getParameter("number"); + if ((param == null) && (hdi.size() > 1)) { + resp.sendRedirect("multiHashDataInput.html"); + return; + } int num = 0; if (param != null) { log.debug("Got request for hashdata#" + num); num = Integer.parseInt(param); } - if ((hdi.size() <= num) || (num < 0)){ + if ((hdi.size() <= num) || (num < 0)) { log.warn("Requested hashdatainput exceeds listsize"); resp.sendError(-1); return; diff --git a/BKUOnline/src/main/webapp/finanzonline/iframe.html b/BKUOnline/src/main/webapp/finanzonline/iframe.html index ac2f6c93..144640ce 100644 --- a/BKUOnline/src/main/webapp/finanzonline/iframe.html +++ b/BKUOnline/src/main/webapp/finanzonline/iframe.html @@ -12,7 +12,7 @@
- +
diff --git a/BKUOnline/src/main/webapp/multiHashDataInput.html b/BKUOnline/src/main/webapp/multiHashDataInput.html new file mode 100644 index 00000000..bb03f8ce --- /dev/null +++ b/BKUOnline/src/main/webapp/multiHashDataInput.html @@ -0,0 +1,37 @@ + + + + + +Mehrere Signaturedaten + + + +
+

Diese Signatur enthält mehrere Datenobjekte.
+Die Anzeige dieser wird derzeit nicht unterstützt !

+
+ + \ No newline at end of file diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 8ee70f1a..c453e06e 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -1,19 +1,19 @@ /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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. -*/ + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; import java.util.ArrayList; @@ -37,15 +37,19 @@ import at.gv.egiz.stal.SignRequest; public abstract class AbstractSMCCSTAL implements STAL { private static Log log = LogFactory.getLog(AbstractSMCCSTAL.class); + + public final static int DEFAULT_MAX_RETRIES = 3; protected Locale locale = Locale.getDefault(); -// protected SMCCHelper smccHelper = new SMCCHelper(); + // protected SMCCHelper smccHelper = new SMCCHelper(); protected SignatureCard signatureCard = null; protected static Map handlerMap = new HashMap(); + + protected int maxRetries = DEFAULT_MAX_RETRIES; static { addRequestHandler(InfoboxReadRequest.class, new InfoBoxReadRequestHandler()); -// addRequestHandler(SignRequest.class, new SignRequestHandler()); + // addRequestHandler(SignRequest.class, new SignRequestHandler()); } /** @@ -58,37 +62,61 @@ public abstract class AbstractSMCCSTAL implements STAL { protected abstract BKUGUIFacade getGUI(); @Override - public List handleRequest( - List requestList) { + public List handleRequest(List requestList) { log.debug("Got request list containing " + requestList.size() + " STAL requests"); List responseList = new ArrayList(requestList .size()); + for (STALRequest request : requestList) { log.info("Processing: " + request.getClass()); - SMCCSTALRequestHandler handler = null; - handler = handlerMap.get(request.getClass().getSimpleName()); - if (handler != null) { - if (handler.requireCard()) { - if (waitForCard()) { - responseList.add(new ErrorResponse(6001)); - break; + int retryCounter = 0; + while (retryCounter < maxRetries) { + log.info("Number of retries: "+retryCounter); + SMCCSTALRequestHandler handler = null; + handler = handlerMap.get(request.getClass().getSimpleName()); + if (handler != null) { + if (handler.requireCard()) { + if (waitForCard()) { + responseList.add(new ErrorResponse(6001)); + break; + } } - } - try { - handler = handler.newInstance(); - handler.init(signatureCard, getGUI()); - STALResponse response = handler.handleRequest(request); - if (response != null) { - responseList.add(response); + try { + handler = handler.newInstance(); + handler.init(signatureCard, getGUI()); + STALResponse response = handler.handleRequest(request); + if (response != null) { + if (response instanceof ErrorResponse) { + log.info("Got an error response"); + if (++retryCounter < maxRetries) { + log.info("Retrying"); + signatureCard = null; + } else { + responseList.add(response); + } + } else { + responseList.add(response); + retryCounter = Integer.MAX_VALUE; + break; + } + } else { + log.info("Got null response from handler, assuming quit"); + retryCounter = Integer.MAX_VALUE; + } + } catch (Exception e) { + log.info("Error while handling STAL request:" + e); + if (++retryCounter < maxRetries) { + log.info("Retrying"); + signatureCard = null; + } else { + responseList.add(new ErrorResponse(6000)); + } } - } catch (Exception e) { - log.info("Error while handling STAL request:" + e); - responseList.add(new ErrorResponse(6000)); + } else { + log.error("Cannot find a handler for STAL request: " + request); + responseList.add(new ErrorResponse()); } - } else { - log.error("Cannot find a handler for STAL request: " + request); - responseList.add(new ErrorResponse()); } } return responseList; @@ -112,4 +140,9 @@ public abstract class AbstractSMCCSTAL implements STAL { } this.locale = locale; } + + public void setMaxRetries(int maxRetries) { + this.maxRetries = maxRetries; + } + } -- cgit v1.2.3 From 378f735d14a1f21571a3c3d5d4ae7eab02c5cf3c Mon Sep 17 00:00:00 2001 From: wbauer Date: Fri, 10 Oct 2008 09:12:46 +0000 Subject: added a reset command git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@97 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'smccSTAL/src') diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index c453e06e..9e47aeb8 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -91,6 +91,7 @@ public abstract class AbstractSMCCSTAL implements STAL { log.info("Got an error response"); if (++retryCounter < maxRetries) { log.info("Retrying"); + signatureCard.reset(); signatureCard = null; } else { responseList.add(response); @@ -108,6 +109,7 @@ public abstract class AbstractSMCCSTAL implements STAL { log.info("Error while handling STAL request:" + e); if (++retryCounter < maxRetries) { log.info("Retrying"); + signatureCard.reset(); signatureCard = null; } else { responseList.add(new ErrorResponse(6000)); -- cgit v1.2.3 From 8852be703a5cacaf271575ccee04bbe27612d16b Mon Sep 17 00:00:00 2001 From: wbauer Date: Fri, 10 Oct 2008 12:35:07 +0000 Subject: Improved Quit Handling for multiple applet instances git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@101 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/bku/online/applet/BKUApplet.java | 4 + .../at/gv/egiz/bku/online/applet/BKUWorker.java | 125 ++++++++++++--------- .../bku/online/applet/MultiInstanceHandler.java | 49 ++++++++ .../at/gv/egiz/bku/online/applet/QuitHandler.java | 37 ++++++ .../at/gv/egiz/smcc/AbstractSignatureCard.java | 6 +- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 4 +- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 2 +- .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 4 +- 8 files changed, 167 insertions(+), 64 deletions(-) create mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/MultiInstanceHandler.java create mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/QuitHandler.java (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java index 6a781729..ab38c163 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java @@ -30,6 +30,9 @@ import org.apache.commons.logging.LogFactory; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.BKUGUIFactory; +import at.gv.egiz.bku.smccstal.AbstractSMCCSTAL; +import at.gv.egiz.stal.QuitRequest; + import java.net.URL; /** @@ -56,6 +59,7 @@ public class BKUApplet extends JApplet { public void init() { log.info("Welcome to MOCCA\n"); log.debug("Called init()"); + AbstractSMCCSTAL.addRequestHandler(QuitRequest.class, QuitHandler.getInstance()); HttpsURLConnection.setDefaultSSLSocketFactory(InternalSSLSocketFactory.getInstance()); String localeString = getMyAppletParameter(LOCALE_PARAM_KEY); if (localeString != null) { diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java index 12eb9d00..fbf74162 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java @@ -48,7 +48,7 @@ import at.gv.egiz.stal.service.types.ResponseType; import at.gv.egiz.stal.util.STALTranslator; public class BKUWorker extends AbstractSMCCSTAL implements Runnable, - ActionListener, SMCCSTALRequestHandler { + ActionListener, SMCCSTALRequestHandler { private static Log log = LogFactory.getLog(BKUWorker.class); protected BKUGUIFacade gui; @@ -65,15 +65,15 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, * must not be null */ public BKUWorker(BKUGUIFacade gui, BKUApplet parent, - ResourceBundle errorMessageBundle) { + ResourceBundle errorMessageBundle) { if ((gui == null) || (parent == null) || (errorMessageBundle == null)) { throw new NullPointerException("Parameter must not be set to null"); } this.gui = gui; this.parent = parent; this.errorMessages = errorMessageBundle; - addRequestHandler(QuitRequest.class, this); - // register SignRequestHandler once we have a webservice port + QuitHandler.getInstance().registerHandlerInstance(this); + // register SignRequestHandler once we have a webservice port } /** @@ -85,7 +85,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, protected BKUWorker(BKUGUIFacade gui, ResourceBundle errorMessageBundle) { this.gui = gui; this.errorMessages = errorMessageBundle; - addRequestHandler(QuitRequest.class, this); + QuitHandler.getInstance().registerHandlerInstance(this); } private STALPortType getSTALPort() throws MalformedURLException { @@ -111,7 +111,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, } log.debug("Found WSDL url: " + wsdlURL); QName endpointName = new QName("http://www.egiz.gv.at/wsdl/stal", - "STALService"); + "STALService"); STALService stal = new STALService(wsdlURL, endpointName); return stal.getSTALPort(); } @@ -126,7 +126,8 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, log.fatal("Failed to call STAL service.", e); actionCommandList.clear(); actionCommandList.add("ok"); - gui.showErrorDialog(BKUGUIFacade.ERR_SERVICE_UNREACHABLE, new Object[] {e.getMessage()}); + gui.showErrorDialog(BKUGUIFacade.ERR_SERVICE_UNREACHABLE, + new Object[] { e.getMessage() }); try { waitForAction(); } catch (InterruptedException e1) { @@ -140,13 +141,16 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, // use the testsession for testing sessionId = "TestSession"; } - addRequestHandler(at.gv.egiz.stal.SignRequest.class, new WSSignRequestHandler(sessionId, stalPort)); + addRequestHandler(at.gv.egiz.stal.SignRequest.class, + new WSSignRequestHandler(sessionId, stalPort)); ObjectFactory of = new ObjectFactory(); GetNextRequestResponseType nextRequestResp = stalPort.connect(sessionId); do { - List requests = nextRequestResp.getInfoboxReadRequestOrSignRequestOrQuitRequest(); - List stalRequests = STALTranslator.translateRequests(requests); + List requests = nextRequestResp + .getInfoboxReadRequestOrSignRequestOrQuitRequest(); + List stalRequests = STALTranslator + .translateRequests(requests); if (log.isInfoEnabled()) { StringBuilder sb = new StringBuilder("Received "); @@ -190,27 +194,33 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, responses = new ArrayList(1); ErrorResponseType err = new ErrorResponseType(); err.setErrorCode(6002); -// err.setErrorMessage(); + // err.setErrorMessage(); responses.add(err); } if (!finished) { + log.info("Not finished yet (BKUWorker: " + this + + "), sending responses"); GetNextRequestType nextRequest = of.createGetNextRequestType(); nextRequest.setSessionId(sessionId); - nextRequest.getInfoboxReadResponseOrSignResponseOrErrorResponse().addAll(responses); + nextRequest.getInfoboxReadResponseOrSignResponseOrErrorResponse() + .addAll(responses); nextRequestResp = stalPort.getNextRequest(nextRequest); } } while (!finished); log.info("Done " + Thread.currentThread().getName()); } catch (Exception ex) { log.error(ex.getMessage(), ex); - gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {ex.getMessage()}); + gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] { ex + .getMessage() }); try { waitForAction(); } catch (InterruptedException e) { log.error(e); } } + signatureCard.disconnect(false); + QuitHandler.getInstance().unregisterHandlerInstance(this); sendRedirect(); } @@ -222,17 +232,20 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, URL url = null; if (redirectURL != null) { try { - url = new URL(parent.getCodeBase(), redirectURL + ";jsessionid=" + parent.getMyAppletParameter(BKUApplet.SESSION_ID)); + url = new URL(parent.getCodeBase(), redirectURL + ";jsessionid=" + + parent.getMyAppletParameter(BKUApplet.SESSION_ID)); } catch (MalformedURLException ex) { - log.warn("Parameter 'redirectURL': " + redirectURL + " not a valid URL.", ex); - // gui.showErrorDialog(errorMsg, okListener, actionCommand) + log.warn("Parameter 'redirectURL': " + redirectURL + + " not a valid URL.", ex); + // gui.showErrorDialog(errorMsg, okListener, actionCommand) } if (url != null) { if (redirectTarget == null) { log.info("Done. Trying to redirect to " + url + " ..."); parent.getAppletContext().showDocument(url); } else { - log.info("Done. Trying to redirect to " + url + " (target=" + redirectTarget + ") ..."); + log.info("Done. Trying to redirect to " + url + " (target=" + + redirectTarget + ") ..."); parent.getAppletContext().showDocument(url, redirectTarget); } } @@ -276,46 +289,46 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, int oldValue = SMCCHelper.PC_SC_NOT_SUPPORTED; // this is a save default while ((signatureCard == null) && (!actionPerformed)) { switch (smccHelper.getResultCode()) { - case SMCCHelper.PC_SC_NOT_SUPPORTED: + case SMCCHelper.PC_SC_NOT_SUPPORTED: + actionCommandList.clear(); + actionCommandList.add("ok"); + gui.showErrorDialog(BKUGUIFacade.ERR_NO_PCSC, null, this, "ok"); + try { + waitForAction(); + } catch (InterruptedException e) { + log.error(e); + } + return true; + case SMCCHelper.TERMINAL_NOT_PRESENT: + actionCommandList.clear(); + actionCommandList.add("ok"); + gui.showErrorDialog(BKUGUIFacade.ERR_NO_CARDTERMINAL, null, this, "ok"); + try { + waitForAction(); + } catch (InterruptedException e) { + log.error(e); + } + return true; + case SMCCHelper.CARD_NOT_SUPPORTED: + if (oldValue != SMCCHelper.CARD_NOT_SUPPORTED) { actionCommandList.clear(); - actionCommandList.add("ok"); - gui.showErrorDialog(BKUGUIFacade.ERR_NO_PCSC, null, this, "ok"); - try { - waitForAction(); - } catch (InterruptedException e) { - log.error(e); - } - return true; - case SMCCHelper.TERMINAL_NOT_PRESENT: + actionCommandList.add("cancel"); + gui.showCardNotSupportedDialog(this, "cancel"); + oldValue = SMCCHelper.CARD_NOT_SUPPORTED; + } + break; + case SMCCHelper.NO_CARD: + if (oldValue != SMCCHelper.NO_CARD) { actionCommandList.clear(); - actionCommandList.add("ok"); - gui.showErrorDialog(BKUGUIFacade.ERR_NO_CARDTERMINAL,null,this,"ok"); - try { - waitForAction(); - } catch (InterruptedException e) { - log.error(e); - } - return true; - case SMCCHelper.CARD_NOT_SUPPORTED: - if (oldValue != SMCCHelper.CARD_NOT_SUPPORTED) { - actionCommandList.clear(); - actionCommandList.add("cancel"); - gui.showCardNotSupportedDialog(this, "cancel"); - oldValue = SMCCHelper.CARD_NOT_SUPPORTED; - } - break; - case SMCCHelper.NO_CARD: - if (oldValue != SMCCHelper.NO_CARD) { - actionCommandList.clear(); - actionCommandList.add("cancel"); - gui.showInsertCardDialog(this, "cancel"); - oldValue = SMCCHelper.NO_CARD; - } - break; - case SMCCHelper.CARD_FOUND: - // gui.showWaitDialog(null); - signatureCard = smccHelper.getSignatureCard(errorMessages.getLocale()); - return false; + actionCommandList.add("cancel"); + gui.showInsertCardDialog(this, "cancel"); + oldValue = SMCCHelper.NO_CARD; + } + break; + case SMCCHelper.CARD_FOUND: + // gui.showWaitDialog(null); + signatureCard = smccHelper.getSignatureCard(errorMessages.getLocale()); + return false; } smccHelper.update(3000); } @@ -325,6 +338,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, @Override public STALResponse handleRequest(STALRequest request) { if (request instanceof QuitRequest) { + log.info("Setting state to: finished for BKUWorker " + this); finished = true; } else { log.error("Unexpected request to handle: " + request); @@ -350,4 +364,5 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, protected BKUGUIFacade getGUI() { return gui; } + } diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/MultiInstanceHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/MultiInstanceHandler.java new file mode 100644 index 00000000..a07df559 --- /dev/null +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/MultiInstanceHandler.java @@ -0,0 +1,49 @@ +package at.gv.egiz.bku.online.applet; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.stal.QuitRequest; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +public abstract class MultiInstanceHandler implements SMCCSTALRequestHandler { + + private static Log log = LogFactory.getLog(MultiInstanceHandler.class); + + protected List handlerList = new ArrayList(); + + + + protected MultiInstanceHandler() { + } + + public void registerHandlerInstance(SMCCSTALRequestHandler handler) { + handlerList.add(handler); + } + + public void unregisterHandlerInstance(SMCCSTALRequestHandler handler) { + handlerList.remove(handler); + } + + + @Override + public void init(SignatureCard sc, BKUGUIFacade gui) { + } + + @Override + public SMCCSTALRequestHandler newInstance() { + return this; + } + + @Override + public boolean requireCard() { + return false; + } +} diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/QuitHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/QuitHandler.java new file mode 100644 index 00000000..ab07e1a8 --- /dev/null +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/QuitHandler.java @@ -0,0 +1,37 @@ +package at.gv.egiz.bku.online.applet; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; +import at.gv.egiz.stal.QuitRequest; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +public class QuitHandler extends MultiInstanceHandler { + + private static Log log = LogFactory.getLog(QuitHandler.class); + + private static QuitHandler instance = new QuitHandler(); + + private QuitHandler() { + } + + public static QuitHandler getInstance() { + return instance; + } + + @Override + public STALResponse handleRequest(STALRequest request) { + if (request instanceof QuitRequest) { + log.info("Received QuitCommand"); + for (SMCCSTALRequestHandler handler : handlerList) { + handler.handleRequest(request); + } + } else { + log.error("Unexpected request to handle: " + request); + } + return null; + } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java index ab6932d7..7f3a3b1c 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -262,11 +262,11 @@ public abstract class AbstractSignatureCard implements SignatureCard { } @Override - public void reset() { - log.debug("Resetting card"); + public void disconnect(boolean reset) { + log.debug("Disconnect called"); if (card_ != null) { try { - card_.disconnect(true); + card_.disconnect(reset); } catch (CardException e) { log.info("Error while resetting card", e); } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java index 28cce350..68a6f6df 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -320,9 +320,7 @@ public class SWCard implements SignatureCard { } @Override - public void reset() { - // TODO Auto-generated method stub - + public void disconnect(boolean reset) { } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index 5e859d52..37bd7cf9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -79,7 +79,7 @@ public interface SignatureCard { public byte[] getCertificate(KeyboxName keyboxName) throws SignatureCardException; - public void reset(); + public void disconnect(boolean reset); /** * diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 9e47aeb8..b7697db1 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -91,7 +91,7 @@ public abstract class AbstractSMCCSTAL implements STAL { log.info("Got an error response"); if (++retryCounter < maxRetries) { log.info("Retrying"); - signatureCard.reset(); + signatureCard.disconnect(true); signatureCard = null; } else { responseList.add(response); @@ -109,7 +109,7 @@ public abstract class AbstractSMCCSTAL implements STAL { log.info("Error while handling STAL request:" + e); if (++retryCounter < maxRetries) { log.info("Retrying"); - signatureCard.reset(); + signatureCard.disconnect(true); signatureCard = null; } else { responseList.add(new ErrorResponse(6000)); -- cgit v1.2.3 From 255269ab17404fa1249c257e88815cbbee6e0d0f Mon Sep 17 00:00:00 2001 From: clemenso Date: Mon, 13 Oct 2008 12:53:57 +0000 Subject: ExternalDisplaySignRequestHandler git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@105 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/bku/online/applet/BKUApplet.java | 1 + .../at/gv/egiz/bku/online/applet/BKUWorker.java | 32 +++- .../applet/ExternalDisplaySignRequestHandler.java | 45 +++++ .../online/applet/SignRequestHandlerFactory.java | 21 +++ .../bku/online/applet/WSSignRequestHandler.java | 168 ------------------- .../applet/WebServiceSignRequestHandler.java | 167 ++++++++++++++++++ .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 1 + .../at/gv/egiz/bku/gui/Messages.properties | 1 + .../src/main/resources/images/chipperling_only.png | Bin 0 -> 3291 bytes .../main/resources/images/mocca_chipperling.png | Bin 0 -> 4103 bytes .../bku/local/stal/LocalSignRequestHandler.java | 93 +++++++---- BKUOnline/src/main/webapp/appletPage.jsp | 1 + .../bku/smccstal/CashedHashDataInputResolver.java | 27 --- .../gv/egiz/bku/smccstal/HashDataInputDisplay.java | 30 ++++ .../gv/egiz/bku/smccstal/SignRequestHandler.java | 186 ++++++--------------- 15 files changed, 407 insertions(+), 366 deletions(-) create mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/ExternalDisplaySignRequestHandler.java create mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/SignRequestHandlerFactory.java delete mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java create mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WebServiceSignRequestHandler.java create mode 100644 BKUCommonGUI/src/main/resources/images/chipperling_only.png create mode 100644 BKUCommonGUI/src/main/resources/images/mocca_chipperling.png delete mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/CashedHashDataInputResolver.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java index ab38c163..32c4feaa 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java @@ -46,6 +46,7 @@ public class BKUApplet extends JApplet { public final static String LOCALE_PARAM_KEY = "Locale"; public final static String LOGO_URL_KEY = "LogoURL"; public final static String WSDL_URL = "WSDL_URL"; + public final static String HASHDATA_URL = "HashDataURL"; public final static String SESSION_ID = "SessionID"; public static final String BACKGROUND_PARAM = "background"; diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java index fbf74162..d5ba4e40 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java @@ -46,6 +46,7 @@ import at.gv.egiz.stal.service.types.ErrorResponseType; import at.gv.egiz.stal.service.types.RequestType; import at.gv.egiz.stal.service.types.ResponseType; import at.gv.egiz.stal.util.STALTranslator; +import java.applet.AppletContext; public class BKUWorker extends AbstractSMCCSTAL implements Runnable, ActionListener, SMCCSTALRequestHandler { @@ -54,6 +55,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, protected BKUGUIFacade gui; protected BKUApplet parent; private STALPortType stalPort; + private URL hashDataURL; protected List actionCommandList = new ArrayList(); protected Boolean actionPerformed = false; protected boolean finished = false; @@ -115,13 +117,30 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, STALService stal = new STALService(wsdlURL, endpointName); return stal.getSTALPort(); } + + private URL getHashDataURL() throws MalformedURLException { + String hashDataParam = parent.getMyAppletParameter(BKUApplet.HASHDATA_URL); + URL codebase = parent.getCodeBase(); + if (hashDataParam != null) { + try { + return new URL(codebase, hashDataParam); +// log.debug("Found HashDataInputServlet URL: " + hashDataURL); + } catch (MalformedURLException ex) { + log.fatal("Paremeter " + BKUApplet.HASHDATA_URL + " is not a vailid URL.", ex); + throw new MalformedURLException(ex.getMessage()); + } + } else { + log.fatal("Paremeter " + BKUApplet.HASHDATA_URL + " not set"); + throw new MalformedURLException(BKUApplet.HASHDATA_URL + " not set"); + } + } @Override public void run() { gui.showWelcomeDialog(); try { stalPort = getSTALPort(); - + hashDataURL = getHashDataURL(); } catch (Exception e) { log.fatal("Failed to call STAL service.", e); actionCommandList.clear(); @@ -135,14 +154,21 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, } return; } + + //TODO factory for SignRequestHandler providing either WebServiceHDISignRequestHandler or ExternalHDIDisplaySignRequestHandler + AppletContext ctx = parent.getAppletContext(); + log.debug("register SignRequestHandler for HashDataURL " + hashDataURL); + addRequestHandler(at.gv.egiz.stal.SignRequest.class, new ExternalDisplaySignRequestHandler(ctx, hashDataURL)); + try { String sessionId = parent.getMyAppletParameter(BKUApplet.SESSION_ID); if (sessionId == null) { // use the testsession for testing sessionId = "TestSession"; } - addRequestHandler(at.gv.egiz.stal.SignRequest.class, - new WSSignRequestHandler(sessionId, stalPort)); + +// log.debug("register SignRequestHandler for STAL port " + BKUApplet.WSDL_URL); +// addRequestHandler(at.gv.egiz.stal.SignRequest.class, new WebServiceSignRequestHandler(sessionId, stalPort)); ObjectFactory of = new ObjectFactory(); GetNextRequestResponseType nextRequestResp = stalPort.connect(sessionId); diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/ExternalDisplaySignRequestHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/ExternalDisplaySignRequestHandler.java new file mode 100644 index 00000000..a9bbc559 --- /dev/null +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/ExternalDisplaySignRequestHandler.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package at.gv.egiz.bku.online.applet; + +import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; +import at.gv.egiz.bku.smccstal.SignRequestHandler; +import at.gv.egiz.stal.signedinfo.ReferenceType; +import java.applet.AppletContext; +import java.net.URL; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author clemens + */ +public class ExternalDisplaySignRequestHandler extends SignRequestHandler { + + private static final Log log = LogFactory.getLog(ExternalDisplaySignRequestHandler.class); + + AppletContext ctx; + URL hashDataURL; + + public ExternalDisplaySignRequestHandler(AppletContext ctx, URL hashDataURL) { + this.ctx = ctx; + this.hashDataURL = hashDataURL; + } + + @Override + public SMCCSTALRequestHandler newInstance() { + return new ExternalDisplaySignRequestHandler(ctx, hashDataURL); + } + + @Override + public void displayHashDataInputs(List signedReferences) throws Exception { + //TODO pass reference Id's to servlet (TODO servlet) + log.debug("displaying hashdata inputs at " + hashDataURL); + ctx.showDocument(hashDataURL, "_blank"); + } + +} diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/SignRequestHandlerFactory.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/SignRequestHandlerFactory.java new file mode 100644 index 00000000..327ea8aa --- /dev/null +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/SignRequestHandlerFactory.java @@ -0,0 +1,21 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package at.gv.egiz.bku.online.applet; + +import at.gv.egiz.bku.smccstal.SignRequestHandler; + +/** + * + * @author clemens + */ +public class SignRequestHandlerFactory { + + static SignRequestHandler getInstance() { + //TODO return ExternalDisplaySignRequestHandler by default, WebServiceSignRequestHandler if requested + //TODO get configuration as param + return null; + } +} diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java deleted file mode 100644 index 3a36a290..00000000 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WSSignRequestHandler.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * 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 at.gv.egiz.bku.online.applet; - -import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; -import at.gv.egiz.bku.smccstal.SignRequestHandler; -import at.gv.egiz.stal.HashDataInput; -import at.gv.egiz.stal.impl.ByteArrayHashDataInput; -import at.gv.egiz.stal.service.STALPortType; -import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; -import at.gv.egiz.stal.service.types.GetHashDataInputType; -import at.gv.egiz.stal.signedinfo.DigestMethodType; -import at.gv.egiz.stal.signedinfo.ReferenceType; -import java.security.DigestException; -import java.security.MessageDigest; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map.Entry; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author clemens - */ -public class WSSignRequestHandler extends SignRequestHandler { - - private static final Log log = LogFactory.getLog(WSSignRequestHandler.class); - STALPortType stalPort; - String sessId; - - public WSSignRequestHandler(String sessId, STALPortType stalPort) { - if (stalPort == null || sessId == null) { - throw new NullPointerException("STAL port must not be null"); - } - this.sessId = sessId; - this.stalPort = stalPort; - } - - @Override - public List getCashedHashDataInputs(List signedReferences) throws Exception { - - GetHashDataInputType request = new GetHashDataInputType(); - request.setSessionId(sessId); - - HashMap idSignedRefMap = new HashMap(); - for (ReferenceType signedRef : signedReferences) { - //don't get Manifest, QualifyingProperties, ... - if (signedRef.getType() == null) { - String signedRefId = signedRef.getId(); - if (signedRefId != null) { - if (log.isTraceEnabled()) { - log.trace("requesting hashdata input for reference " + signedRefId); - } - idSignedRefMap.put(signedRefId, signedRef); - GetHashDataInputType.Reference ref = new GetHashDataInputType.Reference(); - ref.setID(signedRefId); - request.getReference().add(ref); - - } else { - throw new Exception("Cannot resolve HashDataInput for reference without Id attribute"); - } - } - } - - if (log.isDebugEnabled()) { - log.debug("Calling GetHashDataInput for " + request.getReference().size() + " references in session " + sessId); - } - GetHashDataInputResponseType response = stalPort.getHashDataInput(request); - ArrayList hashDataInputs = new ArrayList(); - - //hashdata inputs returned from service - HashMap idRefMap = new HashMap(); - for (GetHashDataInputResponseType.Reference reference : response.getReference()) { - String id = reference.getID(); - byte[] hdi = reference.getValue(); - if (hdi == null) { - throw new Exception("Did not receive hashdata input for reference " + id); - } - idRefMap.put(id, reference); - } - - for (String signedRefId : idSignedRefMap.keySet()) { - log.info("validating hashdata input for reference " + signedRefId); - - GetHashDataInputResponseType.Reference reference = idRefMap.get(signedRefId); - if (reference == null) { - throw new Exception("No hashdata input for reference " + signedRefId + " returned by service"); - } - -// } -// -// for (GetHashDataInputResponseType.Reference reference : response.getReference()) { -// -// String id = reference.getID(); - byte[] hdi = reference.getValue(); - String mimeType = reference.getMimeType(); - String encoding = reference.getEncoding(); - - if (hdi == null) { - throw new Exception("No hashdata input provided for reference " + signedRefId); - } - if (log.isDebugEnabled()) { - log.debug("Got HashDataInput " + signedRefId + " (" + mimeType + ";" + encoding + ")"); - } - - ReferenceType dsigRef = idSignedRefMap.get(signedRefId); - DigestMethodType dm = dsigRef.getDigestMethod(); - - if (dm == null) { - throw new Exception("Failed to verify digest value for reference " + signedRefId + ": no digest algorithm"); - } - String mdAlg = dm.getAlgorithm(); - if ("http://www.w3.org/2000/09/xmldsig#sha1".equals(mdAlg)) - mdAlg = "SHA-1"; - else if ("http://www.w3.org/2001/04/xmlenc#sha256".equals(mdAlg)) - mdAlg = "SHA-256"; - else if ("http://www.w3.org/2001/04/xmlenc#sha224 ".equals(mdAlg)) - mdAlg = "SHA-224"; - else if ("http://www.w3.org/2001/04/xmldsig-more#sha224 ".equals(mdAlg)) - mdAlg = "SHA-224"; - else if ("http://www.w3.org/2001/04/xmldsig-more#sha384".equals(mdAlg)) - mdAlg = "SHA-384"; - else if ("http://www.w3.org/2001/04/xmlenc#sha512".equals(mdAlg)) - mdAlg = "SHA-512"; - else if ("http://www.w3.org/2001/04/xmldsig-more#md2 ".equals(mdAlg)) - mdAlg = "MD2"; - else if ("http://www.w3.org/2001/04/xmldsig-more#md5".equals(mdAlg)) - mdAlg = "MD5"; - else if ("http://www.w3.org/2001/04/xmlenc#ripemd160 ".equals(mdAlg)) - mdAlg = "RipeMD-160"; - else { - throw new Exception("Failed to verify digest value for reference " + signedRefId + ": unsupported digest algorithm " + mdAlg); - } - MessageDigest md = MessageDigest.getInstance(mdAlg); - byte[] hdiDigest = md.digest(hdi); - if (log.isDebugEnabled()) - log.debug("Comparing digest values... "); - if (!Arrays.equals(hdiDigest, dsigRef.getDigestValue())) { - log.error("digest values differ: " + new String(hdiDigest) + ", " + new String(dsigRef.getDigestValue())); - throw new DigestException("Bad digest value for reference " + signedRefId + ": " + new String(dsigRef.getDigestValue())); - } - hashDataInputs.add(new ByteArrayHashDataInput(hdi, signedRefId, mimeType, encoding)); - } - return hashDataInputs; - } - - @Override - public SMCCSTALRequestHandler newInstance() { - return new WSSignRequestHandler(this.sessId, this.stalPort); - } -} diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WebServiceSignRequestHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WebServiceSignRequestHandler.java new file mode 100644 index 00000000..4a87b8b5 --- /dev/null +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WebServiceSignRequestHandler.java @@ -0,0 +1,167 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.online.applet; + +import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; +import at.gv.egiz.bku.smccstal.SignRequestHandler; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; +import at.gv.egiz.stal.service.STALPortType; +import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputType; +import at.gv.egiz.stal.signedinfo.DigestMethodType; +import at.gv.egiz.stal.signedinfo.ReferenceType; +import java.security.DigestException; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author clemens + */ +public class WebServiceSignRequestHandler extends SignRequestHandler { + + private static final Log log = LogFactory.getLog(WebServiceSignRequestHandler.class); + STALPortType stalPort; + String sessId; + + public WebServiceSignRequestHandler(String sessId, STALPortType stalPort) { + if (stalPort == null || sessId == null) { + throw new NullPointerException("STAL port must not be null"); + } + this.sessId = sessId; + this.stalPort = stalPort; + } + + @Override + public void displayHashDataInputs(List signedReferences) throws Exception { + + GetHashDataInputType request = new GetHashDataInputType(); + request.setSessionId(sessId); + + HashMap idSignedRefMap = new HashMap(); + for (ReferenceType signedRef : signedReferences) { + //don't get Manifest, QualifyingProperties, ... + if (signedRef.getType() == null) { + String signedRefId = signedRef.getId(); + if (signedRefId != null) { + if (log.isTraceEnabled()) { + log.trace("requesting hashdata input for reference " + signedRefId); + } + idSignedRefMap.put(signedRefId, signedRef); + GetHashDataInputType.Reference ref = new GetHashDataInputType.Reference(); + ref.setID(signedRefId); + request.getReference().add(ref); + + } else { + throw new Exception("Cannot resolve HashDataInput for reference without Id attribute"); + } + } + } + + if (log.isDebugEnabled()) { + log.debug("Calling GetHashDataInput for " + request.getReference().size() + " references in session " + sessId); + } + GetHashDataInputResponseType response = stalPort.getHashDataInput(request); + ArrayList hashDataInputs = new ArrayList(); + + //hashdata inputs returned from service + HashMap idRefMap = new HashMap(); + for (GetHashDataInputResponseType.Reference reference : response.getReference()) { + String id = reference.getID(); + byte[] hdi = reference.getValue(); + if (hdi == null) { + throw new Exception("Did not receive hashdata input for reference " + id); + } + idRefMap.put(id, reference); + } + + for (String signedRefId : idSignedRefMap.keySet()) { + log.info("validating hashdata input for reference " + signedRefId); + + GetHashDataInputResponseType.Reference reference = idRefMap.get(signedRefId); + if (reference == null) { + throw new Exception("No hashdata input for reference " + signedRefId + " returned by service"); + } + +// } +// +// for (GetHashDataInputResponseType.Reference reference : response.getReference()) { +// +// String id = reference.getID(); + byte[] hdi = reference.getValue(); + String mimeType = reference.getMimeType(); + String encoding = reference.getEncoding(); + + if (hdi == null) { + throw new Exception("No hashdata input provided for reference " + signedRefId); + } + if (log.isDebugEnabled()) { + log.debug("Got HashDataInput " + signedRefId + " (" + mimeType + ";" + encoding + ")"); + } + + ReferenceType dsigRef = idSignedRefMap.get(signedRefId); + DigestMethodType dm = dsigRef.getDigestMethod(); + + if (dm == null) { + throw new Exception("Failed to verify digest value for reference " + signedRefId + ": no digest algorithm"); + } + String mdAlg = dm.getAlgorithm(); + if ("http://www.w3.org/2000/09/xmldsig#sha1".equals(mdAlg)) + mdAlg = "SHA-1"; + else if ("http://www.w3.org/2001/04/xmlenc#sha256".equals(mdAlg)) + mdAlg = "SHA-256"; + else if ("http://www.w3.org/2001/04/xmlenc#sha224 ".equals(mdAlg)) + mdAlg = "SHA-224"; + else if ("http://www.w3.org/2001/04/xmldsig-more#sha224 ".equals(mdAlg)) + mdAlg = "SHA-224"; + else if ("http://www.w3.org/2001/04/xmldsig-more#sha384".equals(mdAlg)) + mdAlg = "SHA-384"; + else if ("http://www.w3.org/2001/04/xmlenc#sha512".equals(mdAlg)) + mdAlg = "SHA-512"; + else if ("http://www.w3.org/2001/04/xmldsig-more#md2 ".equals(mdAlg)) + mdAlg = "MD2"; + else if ("http://www.w3.org/2001/04/xmldsig-more#md5".equals(mdAlg)) + mdAlg = "MD5"; + else if ("http://www.w3.org/2001/04/xmlenc#ripemd160 ".equals(mdAlg)) + mdAlg = "RipeMD-160"; + else { + throw new Exception("Failed to verify digest value for reference " + signedRefId + ": unsupported digest algorithm " + mdAlg); + } + MessageDigest md = MessageDigest.getInstance(mdAlg); + byte[] hdiDigest = md.digest(hdi); + if (log.isDebugEnabled()) + log.debug("Comparing digest values... "); + if (!Arrays.equals(hdiDigest, dsigRef.getDigestValue())) { + log.error("digest values differ: " + new String(hdiDigest) + ", " + new String(dsigRef.getDigestValue())); + throw new DigestException("Bad digest value for reference " + signedRefId + ": " + new String(dsigRef.getDigestValue())); + } + hashDataInputs.add(new ByteArrayHashDataInput(hdi, signedRefId, mimeType, encoding)); + } + + gui.showHashDataInputDialog(hashDataInputs, this, "ok"); + } + + @Override + public SMCCSTALRequestHandler newInstance() { + return new WebServiceSignRequestHandler(this.sessId, this.stalPort); + } +} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index 4925e7fa..0b617271 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -30,6 +30,7 @@ public interface BKUGUIFacade { public static final String ERR_NO_PCSC = "error.pcsc"; public static final String ERR_NO_CARDTERMINAL = "error.cardterminal"; public static final String ERR_NO_HASHDATA = "error.no.hashdata"; + public static final String ERR_DISPLAY_HASHDATA = "error.display.hashdata"; public static final String ERR_WRITE_HASHDATA = "error.write.hashdata"; public static final String ERR_INVALID_HASH = "error.invalid.hash"; diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index abed420f..e7716ae9 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -50,6 +50,7 @@ save.hashdatainput.prefix=Signaturdaten # Error Messages error.no.hashdata=Keine Signaturdaten verf\u00FCgbar: {0} +error.display.hashdata=Signaturdaten konnten nicht dargestellt werden: {0} error.write.hashdata=Die Signaturdaten konnten nicht gespeichert werden: {0} error.invalid.hash=Die Signaturdaten sind ung\u00FCltig: {0} error.ws.unreachable=Das Web-Service ist nicht erreichbar: {0} diff --git a/BKUCommonGUI/src/main/resources/images/chipperling_only.png b/BKUCommonGUI/src/main/resources/images/chipperling_only.png new file mode 100644 index 00000000..57063b9a Binary files /dev/null and b/BKUCommonGUI/src/main/resources/images/chipperling_only.png differ diff --git a/BKUCommonGUI/src/main/resources/images/mocca_chipperling.png b/BKUCommonGUI/src/main/resources/images/mocca_chipperling.png new file mode 100644 index 00000000..4ee2d054 Binary files /dev/null and b/BKUCommonGUI/src/main/resources/images/mocca_chipperling.png differ diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java index ca420f13..4330f570 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java @@ -17,6 +17,7 @@ package at.gv.egiz.bku.local.stal; import at.gv.egiz.bku.slcommands.impl.DataObjectHashDataInput; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -41,68 +42,92 @@ import java.io.InputStream; */ public class LocalSignRequestHandler extends SignRequestHandler { - private static final Log log = LogFactory - .getLog(LocalSignRequestHandler.class); - private List hashDataInput = Collections.EMPTY_LIST; - - public LocalSignRequestHandler() { - } + private static final Log log = LogFactory.getLog(LocalSignRequestHandler.class); + private List hashDataInputs = Collections.EMPTY_LIST; + /** + * If the request is a SIGN request, it contains a list of DataObjectHashDataInput + * providing the pre-digested input stream (that can be obtained repeatedly) if + * reference caching is enabled (or null otherwise). + * @param request + * @return + */ @SuppressWarnings("unchecked") @Override public STALResponse handleRequest(STALRequest request) { if (request instanceof SignRequest) { SignRequest signReq = (SignRequest) request; - hashDataInput = signReq.getHashDataInput(); + hashDataInputs = signReq.getHashDataInput(); } return super.handleRequest(request); } + /** + * + * @param dsigReferences + * @throws java.lang.Exception + */ @Override - public List getCashedHashDataInputs( - List dsigReferences) throws Exception { - ArrayList result = new ArrayList(); + public void displayHashDataInputs(List dsigReferences) throws Exception { + if (dsigReferences == null || dsigReferences.size() < 1) { + log.error("No hashdata input selected to be displayed: null"); + throw new Exception("No HashData Input selected to be displayed"); + } + + ArrayList selectedHashDataInputs = new ArrayList(); for (ReferenceType dsigRef : dsigReferences) { // don't get Manifest, QualifyingProperties, ... if (dsigRef.getType() == null) { String dsigRefId = dsigRef.getId(); if (dsigRefId != null) { - for (HashDataInput hdi : hashDataInput) { - if (hdi.getReferenceId().equals(dsigRefId)) { - if (hdi instanceof DataObjectHashDataInput) { - if (log.isTraceEnabled()) - log.trace("adding DataObjectHashDataInput"); - result.add(hdi); - } else if (hdi instanceof ByteArrayHashDataInput) { - if (log.isTraceEnabled()) - log.trace("adding ByteArrayHashDataInput"); - result.add(hdi); - } else { - if (log.isDebugEnabled()) - log.debug("provided HashDataInput not chaching enabled, creating ByteArrayHashDataInput"); - - InputStream hdIs = hdi.getHashDataInput(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(hdIs.available()); - int b; - while ((b = hdIs.read()) != -1) { - baos.write(b); - } - ByteArrayHashDataInput baHdi = new ByteArrayHashDataInput(baos.toByteArray(), hdi.getReferenceId(), hdi.getMimeType(), hdi.getEncoding()); - result.add(baHdi); + boolean hdiAvailable = false; + for (HashDataInput hashDataInput : hashDataInputs) { + if (dsigRefId.equals(hashDataInput.getReferenceId())) { + log.debug("display hashdata input for dsig:SignedReference " + dsigRefId); + if (!(hashDataInput instanceof DataObjectHashDataInput)) { + log.warn( + "expected DataObjectHashDataInput for LocalSignRequestHandler, got " + hashDataInput.getClass().getName()); + hashDataInput = getByteArrayHashDataInput(hashDataInput); } + selectedHashDataInputs.add(hashDataInput); + hdiAvailable = true; + break; } } + if (!hdiAvailable) { + log.error("no hashdata input for dsig:SignedReference " + dsigRefId); + throw new Exception( + "No HashDataInput available for dsig:SignedReference " + dsigRefId); + } } else { throw new Exception( - "Cannot get HashDataInput for dsig:Reference without Id attribute"); + "Cannot get HashDataInput for dsig:Reference without Id attribute"); } } } - return result; + + if (selectedHashDataInputs.size() < 1) { + log.error("dsig:SignedInfo does not contain a data reference"); + throw new Exception("dsig:SignedInfo does not contain a data reference"); + } + gui.showHashDataInputDialog(selectedHashDataInputs, this, "ok"); } @Override public SMCCSTALRequestHandler newInstance() { return new LocalSignRequestHandler(); } + + private ByteArrayHashDataInput getByteArrayHashDataInput(HashDataInput hashDataInput) throws IOException { + + InputStream hdIs = hashDataInput.getHashDataInput(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(hdIs.available()); + int b; + while ((b = hdIs.read()) != -1) { + baos.write(b); + } + ByteArrayHashDataInput hdi = new ByteArrayHashDataInput(baos.toByteArray(), hashDataInput.getReferenceId(), hashDataInput.getMimeType(), hashDataInput.getEncoding()); + + return hdi; + } } diff --git a/BKUOnline/src/main/webapp/appletPage.jsp b/BKUOnline/src/main/webapp/appletPage.jsp index 6c4aee58..903c762d 100644 --- a/BKUOnline/src/main/webapp/appletPage.jsp +++ b/BKUOnline/src/main/webapp/appletPage.jsp @@ -53,6 +53,7 @@ var parameters = { background : '<%=backgroundImg%>', WSDL_URL :'../stal?wsdl', + HashDataURL : '../hashDataInput', SessionID : '<%=session.getId()%>', redirectURL : '../bkuResult' }; diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/CashedHashDataInputResolver.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/CashedHashDataInputResolver.java deleted file mode 100644 index 05af85d9..00000000 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/CashedHashDataInputResolver.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -package at.gv.egiz.bku.smccstal; - -import at.gv.egiz.stal.HashDataInput; -import at.gv.egiz.stal.impl.ByteArrayHashDataInput; -import at.gv.egiz.stal.signedinfo.ReferenceType; -import java.security.DigestException; -import java.util.List; -import java.util.Set; - -/** - * - * @author clemens - */ -public interface CashedHashDataInputResolver { - - /** - * implementations may verify the hashvalue - * @post-condition returned list != null - * @return - */ - List getCashedHashDataInputs(List signedReferences) throws DigestException, Exception; -} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java new file mode 100644 index 00000000..f79a2027 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java @@ -0,0 +1,30 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package at.gv.egiz.bku.smccstal; + +import at.gv.egiz.stal.signedinfo.ReferenceType; +import java.security.DigestException; +import java.util.List; + +/** + * + * @author clemens + */ +public interface HashDataInputDisplay { + + /** + * Displays the hashdata inputs for all provided dsig:SignedReferences. + * Implementations may verify the digest value if necessary. + * (LocalSignRequestHandler operates on DataObjectHashDataInput, + * other SignRequestHandlers should cache the HashDataInputs obtained by webservice calls, + * or simply forward to a HashDataInputServlet.) + * @param signedReferences The caller may select a subset of the references in SignedInfo to be displayed. + * @throws java.security.DigestException if digest values are verified and do not correspond + * (or any other digest computation error occurs) + * @throws java.lang.Exception + */ + void displayHashDataInputs(List signedReferences) throws DigestException, Exception; + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 7d994392..dcd12b02 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -17,6 +17,7 @@ package at.gv.egiz.bku.smccstal; import at.gv.egiz.bku.gui.BKUGUIFacade; +import java.awt.event.ActionEvent; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.security.MessageDigest; @@ -42,31 +43,18 @@ import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; import at.gv.egiz.stal.SignResponse; -import at.gv.egiz.stal.impl.ByteArrayHashDataInput; import at.gv.egiz.stal.signedinfo.ObjectFactory; -import at.gv.egiz.stal.signedinfo.ReferenceType; import at.gv.egiz.stal.signedinfo.SignedInfoType; import at.gv.egiz.stal.util.JCEAlgorithmNames; -import java.io.ByteArrayOutputStream; -import java.io.IOException; +import java.awt.event.ActionListener; import java.security.DigestException; -import java.security.DigestInputStream; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Set; -/** - * This class is NOT thread-safe. - * handleRequest() sets the SignedInfo which is used in providePIN. - */ -public abstract class SignRequestHandler extends AbstractRequestHandler implements - CashedHashDataInputResolver { +public abstract class SignRequestHandler extends AbstractRequestHandler implements HashDataInputDisplay { private static Log log = LogFactory.getLog(SignRequestHandler.class); private static JAXBContext jaxbContext; - static { try { jaxbContext = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName()); @@ -74,11 +62,6 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen log.fatal("Cannot init jaxbContext", e); } } - /** the SignedInfo of the current SignRequest */ -// protected SignedInfoType signedInfo; -// protected List hashDataInputs; - -// private int retryCounter = 0; @SuppressWarnings("unchecked") @Override @@ -192,99 +175,10 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen // return new SignRequestHandler(); // } - /** - * implementations may verify the hashvalue - * @post-condition returned list != null - * @return - */ - @Override - public abstract List getCashedHashDataInputs(List signedReferences) throws Exception; -// { -// //TODO -// log.warn("Return empty HashDataInput"); -// return new ArrayList(); -// } - + -// protected void validateHashDataInputs(List signedReferences, List hashDataInputs) { -// if (hashDataInputs != null) { -// -// Map hashDataIdMap = new HashMap(); -// for (HashDataInput hdi : hashDataInputs) { -// if (log.isTraceEnabled()) { -// log.trace("Provided HashDataInput for reference " + hdi.getReferenceId()); -// } -// hashDataIdMap.put(hdi.getReferenceId(), hdi); -// } -// -// List reqRefs = request.getReference(); -// for (GetHashDataInputType.Reference reqRef : reqRefs) { -// String reqRefId = reqRef.getID(); -// HashDataInput reqHdi = hashDataIdMap.get(reqRefId); -// if (reqHdi == null) { -// String msg = "Failed to resolve HashDataInput for reference " + reqRefId; -// log.error(msg); -// GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); -// faultInfo.setErrorCode(1); -// faultInfo.setErrorMessage(msg); -// throw new GetHashDataInputFault(msg, faultInfo); -// } -// -// InputStream hashDataIS = reqHdi.getHashDataInput(); -// if (hashDataIS == null) { -// //HashDataInput not cached? -// String msg = "Failed to obtain HashDataInput for reference " + reqRefId + ", reference not cached"; -// log.error(msg); -// GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); -// faultInfo.setErrorCode(1); -// faultInfo.setErrorMessage(msg); -// throw new GetHashDataInputFault(msg, faultInfo); -// } -// ByteArrayOutputStream baos = null; -// try { -// if (log.isDebugEnabled()) { -// log.debug("Resolved HashDataInput " + reqRefId + " (" + reqHdi.getMimeType() + ";charset=" + reqHdi.getEncoding() + ")"); -// } -// baos = new ByteArrayOutputStream(hashDataIS.available()); -// int c; -// while ((c = hashDataIS.read()) != -1) { -// baos.write(c); -// } -// GetHashDataInputResponseType.Reference ref = new GetHashDataInputResponseType.Reference(); -// ref.setID(reqRefId); -// ref.setMimeType(reqHdi.getMimeType()); -// ref.setEncoding(reqHdi.getEncoding()); -// ref.setValue(baos.toByteArray()); -// response.getReference().add(ref); -// } catch (IOException ex) { -// String msg = "Failed to get HashDataInput for reference " + reqRefId; -// log.error(msg, ex); -// GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); -// faultInfo.setErrorCode(1); -// faultInfo.setErrorMessage(msg); -// throw new GetHashDataInputFault(msg, faultInfo, ex); -// } finally { -// try { -// baos.close(); -// } catch (IOException ex) { -// } -// } -// } -// return response; -// } -// for (ReferenceType reference : signedReferences) { -// String algorithm = reference.getDigestMethod().getAlgorithm(); -// -// } -// } - - - /** - * cashes the HashDataInputs provided by SignRequestHandler.this.getHashDataInputs() - * (don't know whether outer class is LocalSignRequestHandler or WSSignRequestHandler, providing DataObjectHDI or ByteArrayHDI, resp) - */ - class STALPinProvider implements PINProvider { + class STALPinProvider implements PINProvider, ActionListener { protected SignedInfoType signedInfo; protected List hashDataInputs; @@ -293,49 +187,73 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen public STALPinProvider(SignedInfoType signedInfo) { this.signedInfo = signedInfo; } + + private void showSignaturePINDialog(PINSpec spec, int retries) { + if (retryCounter > 0) { + gui.showSignaturePINRetryDialog(spec, retries, SignRequestHandler.this, "sign", SignRequestHandler.this, + "cancel", SignRequestHandler.this, "hashData"); + } else { + gui.showSignaturePINDialog(spec, SignRequestHandler.this, "sign", SignRequestHandler.this, "cancel", SignRequestHandler.this, + "hashData"); + } + } @Override public String providePIN(PINSpec spec, int retries) { - if (retryCounter++ > 0) { - log.info("PIN wrong retrying ..."); - gui.showSignaturePINRetryDialog(spec, retries, SignRequestHandler.this, "sign", SignRequestHandler.this, - "cancel", SignRequestHandler.this, "hashData"); - } else { - gui.showSignaturePINDialog(spec, SignRequestHandler.this, "sign", SignRequestHandler.this, "cancel", SignRequestHandler.this, - "hashData"); - } + + showSignaturePINDialog(spec, retries); + do { waitForAction(); gui.showWaitDialog(null); if (actionCommand.equals("cancel")) { return null; } else if (actionCommand.equals("hashData")) { - if (signedInfo != null) { + + showSignaturePINDialog(spec, retries); + try { -// gui.showWaitDialog(null); - if (hashDataInputs == null || hashDataInputs.size() == 0) { - hashDataInputs = getCashedHashDataInputs(signedInfo.getReference()); - } - gui.showHashDataInputDialog(hashDataInputs, SignRequestHandler.this, "ok"); + displayHashDataInputs(signedInfo.getReference()); } catch (DigestException ex) { log.error("Bad digest value: " + ex.getMessage()); gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, new Object[] {ex.getMessage()}); } catch (Exception ex) { - //FIXME localize messages - log.error("Failed to obtain HashDataInputs: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_NO_HASHDATA, new Object[] {ex.getMessage()}, SignRequestHandler.this, "ok"); + log.error("Could not display hashdata inputs: " + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, new Object[] {ex.getMessage()}, SignRequestHandler.this, "ok"); } - } else { - //FIXME get all hashdatainputs - gui.showErrorDialog(BKUGUIFacade.ERR_NO_HASHDATA, new Object[] {"No dsig:SignedInfo provided"}, SignRequestHandler.this, "ok"); - } + + // OLD HASHDATA DISPLAY (in applet), + // register SignRequestHandler.this as hashdataListener to use +// if (signedInfo != null) { +// try { +// if (hashDataInputs == null || hashDataInputs.size() == 0) { +// hashDataInputs = getCashedHashDataInputs(signedInfo.getReference()); +// } +// gui.showHashDataInputDialog(hashDataInputs, SignRequestHandler.this, "ok"); +// } catch (DigestException ex) { +// log.error("Bad digest value: " + ex.getMessage()); +// gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, new Object[] {ex.getMessage()}); +// } catch (Exception ex) { +// //FIXME localize messages +// log.error("Failed to obtain HashDataInputs: " + ex.getMessage()); +// gui.showErrorDialog(BKUGUIFacade.ERR_NO_HASHDATA, new Object[] {ex.getMessage()}, SignRequestHandler.this, "ok"); +// } +// } else { +// //FIXME get all hashdatainputs +// gui.showErrorDialog(BKUGUIFacade.ERR_NO_HASHDATA, new Object[] {"No dsig:SignedInfo provided"}, SignRequestHandler.this, "ok"); +// } } else if (actionCommand.equals("sign")) { + retryCounter++; return new String(gui.getPin()); } else if (actionCommand.equals("ok")) { - gui.showSignaturePINDialog(spec, SignRequestHandler.this, "sign", SignRequestHandler.this, "cancel", SignRequestHandler.this, - "hashData"); + showSignaturePINDialog(spec, retries); } } while (true); } + + @Override + public void actionPerformed(ActionEvent e) { + throw new UnsupportedOperationException("Not supported yet."); + } } } -- cgit v1.2.3 From 70b917ae4b8aece8652dc076e0e1b127a89f5086 Mon Sep 17 00:00:00 2001 From: wbauer Date: Mon, 13 Oct 2008 14:51:56 +0000 Subject: not retrying smcc commands when canceled by user via gui git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@108 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'smccSTAL/src') diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index b7697db1..b48388db 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -89,6 +89,10 @@ public abstract class AbstractSMCCSTAL implements STAL { if (response != null) { if (response instanceof ErrorResponse) { log.info("Got an error response"); + ErrorResponse err = (ErrorResponse) response; + if (err.getErrorCode() == 6001) { + retryCounter = Integer.MAX_VALUE-1; + } if (++retryCounter < maxRetries) { log.info("Retrying"); signatureCard.disconnect(true); -- cgit v1.2.3 From ef8dc449ddc60008bce9264c73b4162cc487c174 Mon Sep 17 00:00:00 2001 From: wbauer Date: Thu, 16 Oct 2008 07:51:13 +0000 Subject: Changed STAL Handler from static registration to one Object per STAL instance git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@121 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/bku/online/applet/BKUApplet.java | 8 +--- .../at/gv/egiz/bku/online/applet/BKUWorker.java | 17 +++----- .../applet/ExternalDisplaySignRequestHandler.java | 12 ++---- .../bku/online/applet/MultiInstanceHandler.java | 49 ---------------------- .../at/gv/egiz/bku/online/applet/QuitHandler.java | 37 ---------------- .../applet/WebServiceSignRequestHandler.java | 24 +++++------ .../bku/local/stal/LocalSignRequestHandler.java | 5 --- .../java/at/gv/egiz/bku/local/stal/SMCCSTAL.java | 2 +- .../at/gv/egiz/bku/local/stal/SMCCSTALFactory.java | 5 +-- .../java/at/gv/egiz/bku/local/app/BKULauncher.java | 2 - .../at/gv/egiz/smcc/AbstractSignatureCard.java | 2 +- .../main/java/at/gv/egiz/smcc/util/SMCCHelper.java | 6 +-- .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 21 ++++------ .../bku/smccstal/InfoBoxReadRequestHandler.java | 5 --- .../egiz/bku/smccstal/SMCCSTALRequestHandler.java | 2 - 15 files changed, 35 insertions(+), 162 deletions(-) delete mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/MultiInstanceHandler.java delete mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/QuitHandler.java (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java index 96c0e7eb..97b5869f 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java @@ -17,11 +17,10 @@ package at.gv.egiz.bku.online.applet; import java.net.MalformedURLException; +import java.net.URL; import java.util.Locale; import java.util.ResourceBundle; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.net.ssl.HttpsURLConnection; import javax.swing.JApplet; @@ -30,10 +29,6 @@ import org.apache.commons.logging.LogFactory; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.BKUGUIFactory; -import at.gv.egiz.bku.smccstal.AbstractSMCCSTAL; -import at.gv.egiz.stal.QuitRequest; - -import java.net.URL; /** * Note: all swing code is executed by the event dispatch thread (see @@ -66,7 +61,6 @@ public class BKUApplet extends JApplet { public void init() { log.info("Welcome to MOCCA\n"); log.debug("Called init()"); - AbstractSMCCSTAL.addRequestHandler(QuitRequest.class, QuitHandler.getInstance()); HttpsURLConnection.setDefaultSSLSocketFactory(InternalSSLSocketFactory.getInstance()); String localeString = getMyAppletParameter(LOCALE_PARAM_KEY); if (localeString != null) { diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java index 3f64de3d..f708826d 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUWorker.java @@ -37,16 +37,15 @@ import at.gv.egiz.smcc.util.SMCCHelper; import at.gv.egiz.stal.QuitRequest; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; -import at.gv.egiz.stal.service.types.GetNextRequestResponseType; -import at.gv.egiz.stal.service.types.GetNextRequestType; -import at.gv.egiz.stal.service.types.ObjectFactory; import at.gv.egiz.stal.service.STALPortType; import at.gv.egiz.stal.service.STALService; import at.gv.egiz.stal.service.types.ErrorResponseType; +import at.gv.egiz.stal.service.types.GetNextRequestResponseType; +import at.gv.egiz.stal.service.types.GetNextRequestType; +import at.gv.egiz.stal.service.types.ObjectFactory; import at.gv.egiz.stal.service.types.RequestType; import at.gv.egiz.stal.service.types.ResponseType; import at.gv.egiz.stal.util.STALTranslator; -import java.applet.AppletContext; public class BKUWorker extends AbstractSMCCSTAL implements Runnable, ActionListener, SMCCSTALRequestHandler { @@ -74,7 +73,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, this.gui = gui; this.parent = parent; this.errorMessages = errorMessageBundle; - QuitHandler.getInstance().registerHandlerInstance(this); + addRequestHandler(QuitRequest.class, this); // register SignRequestHandler once we have a webservice port } @@ -87,7 +86,7 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, protected BKUWorker(BKUGUIFacade gui, ResourceBundle errorMessageBundle) { this.gui = gui; this.errorMessages = errorMessageBundle; - QuitHandler.getInstance().registerHandlerInstance(this); + addRequestHandler(QuitRequest.class, this); } private STALPortType getSTALPort() throws MalformedURLException { @@ -252,7 +251,6 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, if (signatureCard != null) { signatureCard.disconnect(false); } - QuitHandler.getInstance().unregisterHandlerInstance(this); sendRedirect(); } @@ -382,11 +380,6 @@ public class BKUWorker extends AbstractSMCCSTAL implements Runnable, public void init(SignatureCard sc, BKUGUIFacade gui) { } - @Override - public SMCCSTALRequestHandler newInstance() { - return this; - } - @Override public boolean requireCard() { return false; diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/ExternalDisplaySignRequestHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/ExternalDisplaySignRequestHandler.java index a9bbc559..2ac1bc62 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/ExternalDisplaySignRequestHandler.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/ExternalDisplaySignRequestHandler.java @@ -5,15 +5,16 @@ package at.gv.egiz.bku.online.applet; -import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; -import at.gv.egiz.bku.smccstal.SignRequestHandler; -import at.gv.egiz.stal.signedinfo.ReferenceType; import java.applet.AppletContext; import java.net.URL; import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import at.gv.egiz.bku.smccstal.SignRequestHandler; +import at.gv.egiz.stal.signedinfo.ReferenceType; + /** * * @author clemens @@ -30,11 +31,6 @@ public class ExternalDisplaySignRequestHandler extends SignRequestHandler { this.hashDataURL = hashDataURL; } - @Override - public SMCCSTALRequestHandler newInstance() { - return new ExternalDisplaySignRequestHandler(ctx, hashDataURL); - } - @Override public void displayHashDataInputs(List signedReferences) throws Exception { //TODO pass reference Id's to servlet (TODO servlet) diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/MultiInstanceHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/MultiInstanceHandler.java deleted file mode 100644 index a07df559..00000000 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/MultiInstanceHandler.java +++ /dev/null @@ -1,49 +0,0 @@ -package at.gv.egiz.bku.online.applet; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; -import at.gv.egiz.smcc.SignatureCard; -import at.gv.egiz.stal.QuitRequest; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; - -public abstract class MultiInstanceHandler implements SMCCSTALRequestHandler { - - private static Log log = LogFactory.getLog(MultiInstanceHandler.class); - - protected List handlerList = new ArrayList(); - - - - protected MultiInstanceHandler() { - } - - public void registerHandlerInstance(SMCCSTALRequestHandler handler) { - handlerList.add(handler); - } - - public void unregisterHandlerInstance(SMCCSTALRequestHandler handler) { - handlerList.remove(handler); - } - - - @Override - public void init(SignatureCard sc, BKUGUIFacade gui) { - } - - @Override - public SMCCSTALRequestHandler newInstance() { - return this; - } - - @Override - public boolean requireCard() { - return false; - } -} diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/QuitHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/QuitHandler.java deleted file mode 100644 index ab07e1a8..00000000 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/QuitHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package at.gv.egiz.bku.online.applet; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; -import at.gv.egiz.stal.QuitRequest; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; - -public class QuitHandler extends MultiInstanceHandler { - - private static Log log = LogFactory.getLog(QuitHandler.class); - - private static QuitHandler instance = new QuitHandler(); - - private QuitHandler() { - } - - public static QuitHandler getInstance() { - return instance; - } - - @Override - public STALResponse handleRequest(STALRequest request) { - if (request instanceof QuitRequest) { - log.info("Received QuitCommand"); - for (SMCCSTALRequestHandler handler : handlerList) { - handler.handleRequest(request); - } - } else { - log.error("Unexpected request to handle: " + request); - } - return null; - } - -} diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WebServiceSignRequestHandler.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WebServiceSignRequestHandler.java index 4a87b8b5..b417fd33 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WebServiceSignRequestHandler.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/WebServiceSignRequestHandler.java @@ -16,24 +16,25 @@ */ package at.gv.egiz.bku.online.applet; -import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; -import at.gv.egiz.bku.smccstal.SignRequestHandler; -import at.gv.egiz.stal.HashDataInput; -import at.gv.egiz.stal.impl.ByteArrayHashDataInput; -import at.gv.egiz.stal.service.STALPortType; -import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; -import at.gv.egiz.stal.service.types.GetHashDataInputType; -import at.gv.egiz.stal.signedinfo.DigestMethodType; -import at.gv.egiz.stal.signedinfo.ReferenceType; import java.security.DigestException; import java.security.MessageDigest; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import at.gv.egiz.bku.smccstal.SignRequestHandler; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; +import at.gv.egiz.stal.service.STALPortType; +import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputType; +import at.gv.egiz.stal.signedinfo.DigestMethodType; +import at.gv.egiz.stal.signedinfo.ReferenceType; + /** * @author clemens */ @@ -159,9 +160,4 @@ public class WebServiceSignRequestHandler extends SignRequestHandler { gui.showHashDataInputDialog(hashDataInputs, this, "ok"); } - - @Override - public SMCCSTALRequestHandler newInstance() { - return new WebServiceSignRequestHandler(this.sessId, this.stalPort); - } } diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java index 4330f570..d5702e0e 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java @@ -113,11 +113,6 @@ public class LocalSignRequestHandler extends SignRequestHandler { gui.showHashDataInputDialog(selectedHashDataInputs, this, "ok"); } - @Override - public SMCCSTALRequestHandler newInstance() { - return new LocalSignRequestHandler(); - } - private ByteArrayHashDataInput getByteArrayHashDataInput(HashDataInput hashDataInput) throws IOException { InputStream hdIs = hashDataInput.getHashDataInput(); diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTAL.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTAL.java index 4bc921aa..1bbb2e3c 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTAL.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTAL.java @@ -27,7 +27,7 @@ public class SMCCSTAL extends BKUWorker { public List handleRequest(List requestList) { signatureCard = null; List responses = super.handleRequest(requestList); - //container.setVisible(false); + // container.setVisible(false); return responses; } diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTALFactory.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTALFactory.java index c5736648..e1d434e3 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTALFactory.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTALFactory.java @@ -27,9 +27,6 @@ import javax.swing.WindowConstants; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.BKUGUIFactory; import at.gv.egiz.bku.online.applet.BKUApplet; -import at.gv.egiz.bku.online.applet.QuitHandler; -import at.gv.egiz.bku.smccstal.AbstractSMCCSTAL; -import at.gv.egiz.stal.QuitRequest; import at.gv.egiz.stal.STAL; import at.gv.egiz.stal.STALFactory; @@ -39,7 +36,7 @@ public class SMCCSTALFactory implements STALFactory { @Override public STAL createSTAL() { - AbstractSMCCSTAL.addRequestHandler(QuitRequest.class, QuitHandler.getInstance()); + SMCCSTAL stal; JDialog dialog; ResourceBundle resourceBundle; diff --git a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/BKULauncher.java b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/BKULauncher.java index 54d595fa..23a893b4 100644 --- a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/BKULauncher.java +++ b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/BKULauncher.java @@ -181,9 +181,7 @@ public class BKULauncher implements BKUControllerInterface { * @param args */ public static void main(String[] args) { - try { - BKULauncher launcher = new BKULauncher(); launcher.initStart(); launcher.checkConfig(args); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java index 7f3a3b1c..77a3e2ea 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -267,7 +267,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { if (card_ != null) { try { card_.disconnect(reset); - } catch (CardException e) { + } catch (Exception e) { log.info("Error while resetting card", e); } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java index 3d1fd7c7..15971497 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java @@ -49,11 +49,11 @@ public class SMCCHelper { update(); } - public void update() { + public synchronized void update() { update(-1); } - public void update(int sleep) { + public synchronized void update(int sleep) { SignatureCardFactory factory = SignatureCardFactory.getInstance(); if (useSWCard) { try { @@ -113,7 +113,7 @@ public class SMCCHelper { } } - public SignatureCard getSignatureCard(Locale locale) { + public synchronized SignatureCard getSignatureCard(Locale locale) { if (signatureCard != null) { signatureCard.setLocale(locale); } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index b48388db..cf524737 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -37,19 +37,17 @@ import at.gv.egiz.stal.SignRequest; public abstract class AbstractSMCCSTAL implements STAL { private static Log log = LogFactory.getLog(AbstractSMCCSTAL.class); - + public final static int DEFAULT_MAX_RETRIES = 3; protected Locale locale = Locale.getDefault(); - // protected SMCCHelper smccHelper = new SMCCHelper(); protected SignatureCard signatureCard = null; - protected static Map handlerMap = new HashMap(); - + protected Map handlerMap = new HashMap(); + protected int maxRetries = DEFAULT_MAX_RETRIES; - static { + protected AbstractSMCCSTAL() { addRequestHandler(InfoboxReadRequest.class, new InfoBoxReadRequestHandler()); - // addRequestHandler(SignRequest.class, new SignRequestHandler()); } /** @@ -72,7 +70,7 @@ public abstract class AbstractSMCCSTAL implements STAL { log.info("Processing: " + request.getClass()); int retryCounter = 0; while (retryCounter < maxRetries) { - log.info("Number of retries: "+retryCounter); + log.info("Number of retries: " + retryCounter); SMCCSTALRequestHandler handler = null; handler = handlerMap.get(request.getClass().getSimpleName()); if (handler != null) { @@ -83,7 +81,6 @@ public abstract class AbstractSMCCSTAL implements STAL { } } try { - handler = handler.newInstance(); handler.init(signatureCard, getGUI()); STALResponse response = handler.handleRequest(request); if (response != null) { @@ -91,7 +88,7 @@ public abstract class AbstractSMCCSTAL implements STAL { log.info("Got an error response"); ErrorResponse err = (ErrorResponse) response; if (err.getErrorCode() == 6001) { - retryCounter = Integer.MAX_VALUE-1; + retryCounter = Integer.MAX_VALUE - 1; } if (++retryCounter < maxRetries) { log.info("Retrying"); @@ -128,13 +125,13 @@ public abstract class AbstractSMCCSTAL implements STAL { return responseList; } - public static void addRequestHandler(Class id, + public void addRequestHandler(Class id, SMCCSTALRequestHandler handler) { log.debug("Registering STAL request handler: " + id.getSimpleName()); handlerMap.put(id.getSimpleName(), handler); } - public static SMCCSTALRequestHandler getRequestHandler( + public SMCCSTALRequestHandler getRequestHandler( Class request) { return handlerMap.get(request.getSimpleName()); } @@ -150,5 +147,5 @@ public abstract class AbstractSMCCSTAL implements STAL { public void setMaxRetries(int maxRetries) { this.maxRetries = maxRetries; } - + } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java index 25085b16..b48d6d50 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java @@ -133,9 +133,4 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements } return new String(gui.getPin()); } - - @Override - public SMCCSTALRequestHandler newInstance() { - return new InfoBoxReadRequestHandler(); - } } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java index 6f303f76..94ab7a5b 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java @@ -30,6 +30,4 @@ public interface SMCCSTALRequestHandler { public boolean requireCard(); - public SMCCSTALRequestHandler newInstance(); - } -- cgit v1.2.3 From c2ae3db1bc6dcb8ba3eb3461c05e293917c004ca Mon Sep 17 00:00:00 2001 From: mcentner Date: Thu, 30 Oct 2008 10:33:29 +0000 Subject: Updated SMCC to use exclusive access and to throw exceptions upon locked or not activated cards. Improved locale support in the security layer request and response processing. Fixed issue in STAL which prevented the use of RSA-SHA1 signatures. Added additional parameters to the applet test pages. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@128 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../main/java/at/gv/egiz/bku/gui/PinDocument.java | 2 +- .../egiz/bku/online/webapp/BKURequestHandler.java | 20 +- BKUOnline/src/main/webapp/HTTP-ohne.html | 11 +- BKUOnline/src/main/webapp/appletPage.jsp | 29 +- .../at/gv/egiz/stal/util/JCEAlgorithmNames.java | 4 +- .../gv/egiz/bku/binding/HTTPBindingProcessor.java | 3 +- .../gv/egiz/bku/slcommands/SLCommandContext.java | 17 +- .../impl/CreateXMLSignatureCommandImpl.java | 4 +- .../egiz/bku/slcommands/impl/ErrorResultImpl.java | 42 ++- .../slcommands/impl/InfoboxReadCommandImpl.java | 2 +- .../gv/egiz/bku/slcommands/impl/SLResultImpl.java | 8 +- .../bku/slcommands/impl/ErrorResultImplTest.java | 3 +- smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 348 ++++++++++++--------- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 169 +++++++--- .../at/gv/egiz/smcc/FileNotFoundException.java | 38 +++ .../main/java/at/gv/egiz/smcc/LockedException.java | 38 +++ .../at/gv/egiz/smcc/NotActivatedException.java | 44 +++ .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 339 ++++++++++++-------- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 79 ++++- .../at/gv/egiz/smcc/SignatureCardException.java | 2 +- .../java/at/gv/egiz/smcc/SignatureCardFactory.java | 223 +++++++++++-- .../java/at/gv/egiz/smcc/util/SmartCardIO.java | 3 +- .../test/java/at/gv/egiz/smcc/STARCOSCardTest.java | 92 ++++++ .../bku/smccstal/InfoBoxReadRequestHandler.java | 8 + .../gv/egiz/bku/smccstal/SignRequestHandler.java | 10 +- 25 files changed, 1149 insertions(+), 389 deletions(-) create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/FileNotFoundException.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/LockedException.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/NotActivatedException.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/STARCOSCardTest.java (limited to 'smccSTAL/src') diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java index 8ae9d7a3..2054ae86 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java @@ -46,7 +46,7 @@ class PINDocument extends PlainDocument { @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { - if (pinSpec.getMaxLength() >= (getLength() + str.length())) { + if (pinSpec.getMaxLength() < 0 || pinSpec.getMaxLength() >= (getLength() + str.length())) { boolean matches = true; for (int i = 0; i < str.length(); i++) { Matcher m = pinPattern.matcher(str.substring(i, i + 1)); diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java index 6f3b9d7f..9092e3f9 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java @@ -44,6 +44,8 @@ import at.gv.egiz.org.apache.tomcat.util.http.AcceptLanguage; */ public class BKURequestHandler extends SpringBKUServlet { + private static final long serialVersionUID = 1L; + public final static String REDIRECT_URL = "appletPage.jsp"; protected Log log = LogFactory.getLog(BKURequestHandler.class); @@ -105,6 +107,8 @@ public class BKURequestHandler extends SpringBKUServlet { String width = getStringFromStream(bindingProcessor.getFormData("appletWidth"), charset); String height = getStringFromStream(bindingProcessor.getFormData("appletHeight"), charset); String background = getStringFromStream(bindingProcessor.getFormData("appletBackground"), charset); + String guiStyle = getStringFromStream(bindingProcessor.getFormData("appletGuiStyle"), charset); + String hashDataDisplay = getStringFromStream(bindingProcessor.getFormData("appletHashDataDisplay"), charset); if (width != null) { try { log.trace("Found applet width parameter: " + width); @@ -124,12 +128,16 @@ public class BKURequestHandler extends SpringBKUServlet { } } if (background != null) { - try { - log.trace("Found applet background parameter: " + background); - session.setAttribute("appletBackground", background); - } catch (NumberFormatException nfe) { - log.warn(nfe); - } + log.trace("Found applet background parameter: " + background); + session.setAttribute("appletBackground", background); + } + if (guiStyle != null) { + log.trace("Found applet GUI style parameter: " + guiStyle); + session.setAttribute("appletGuiStyle", guiStyle); + } + if (hashDataDisplay != null) { + log.trace("Found applet hash data display parameter: " + hashDataDisplay); + session.setAttribute("appletHashDataDisplay", hashDataDisplay); } resp.sendRedirect(REDIRECT_URL); diff --git a/BKUOnline/src/main/webapp/HTTP-ohne.html b/BKUOnline/src/main/webapp/HTTP-ohne.html index 1923113e..044432ce 100644 --- a/BKUOnline/src/main/webapp/HTTP-ohne.html +++ b/BKUOnline/src/main/webapp/HTTP-ohne.html @@ -92,8 +92,17 @@ legend { name="appletHeight" value="130" id="appletHeight">

+

+ + simple + advanced +

+

+ + external + internal +

-

\ No newline at end of file diff --git a/STALService/src/main/java/at/gv/egiz/stal/util/HashDataInputProxy.java b/STALService/src/main/java/at/gv/egiz/stal/util/HashDataInputProxy.java deleted file mode 100644 index 01d207d2..00000000 --- a/STALService/src/main/java/at/gv/egiz/stal/util/HashDataInputProxy.java +++ /dev/null @@ -1,67 +0,0 @@ -package at.gv.egiz.stal.util; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.utils.StreamUtil; -import at.gv.egiz.stal.HashDataInput; - -/** - * Enables multiple read requests. - * @deprecated use at.gv.egiz.stal.impl.ByteArrayHashDataInput - */ -public class HashDataInputProxy implements HashDataInput { - - private static Log log = LogFactory.getLog(HashDataInputProxy.class); - - private HashDataInput delegate; - private byte[] hashInput; - - /** - * - * @param delegate - * != null - */ - public HashDataInputProxy(HashDataInput delegate) { - if (delegate == null) { - throw new NullPointerException("Constructor argument must not be null"); - } - this.delegate = delegate; - } - - @Override - public String getEncoding() { - return delegate.getEncoding(); - } - - @Override - public InputStream getHashDataInput() { - if (hashInput == null) { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - try { - StreamUtil.copyStream(delegate.getHashDataInput(), os); - hashInput = os.toByteArray(); - } catch (IOException e) { - log.error("Cannot access hashdatainput stream", e); - hashInput = new byte[0]; - } - } - return new ByteArrayInputStream(hashInput); - } - - @Override - public String getMimeType() { - return delegate.getMimeType(); - } - - @Override - public String getReferenceId() { - return delegate.getReferenceId(); - } - -} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java index f79a2027..59700d4a 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java @@ -1,6 +1,18 @@ /* - * To change this template, choose Tools | Templates - * and open the template in the editor. + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; @@ -14,7 +26,11 @@ import java.util.List; */ public interface HashDataInputDisplay { + /** + * TODO: (see AbstractHelpListener) + * + * * Displays the hashdata inputs for all provided dsig:SignedReferences. * Implementations may verify the digest value if necessary. * (LocalSignRequestHandler operates on DataObjectHashDataInput, diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 6c30a68a..77ee45b6 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -192,7 +192,7 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen - class STALPinProvider implements PINProvider, ActionListener { + class STALPinProvider implements PINProvider { protected SignedInfoType signedInfo; protected List hashDataInputs; @@ -230,10 +230,10 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen displayHashDataInputs(signedInfo.getReference()); } catch (DigestException ex) { log.error("Bad digest value: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, new Object[] {ex.getMessage()}); + gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, new Object[] {ex.getMessage()}, SignRequestHandler.this, "error"); } catch (Exception ex) { log.error("Could not display hashdata inputs: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, new Object[] {ex.getMessage()}, SignRequestHandler.this, "ok"); + gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, new Object[] {ex.getMessage()}, SignRequestHandler.this, "error"); } // OLD HASHDATA DISPLAY (in applet), @@ -261,13 +261,15 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen return new String(gui.getPin()); } else if (actionCommand.equals("ok")) { showSignaturePINDialog(spec, retries); + } else if (actionCommand.equals("error")) { + return null; } } while (true); } - @Override - public void actionPerformed(ActionEvent e) { - throw new UnsupportedOperationException("Not supported yet."); - } +// @Override +// public void actionPerformed(ActionEvent e) { +// throw new UnsupportedOperationException("Not supported yet."); +// } } } -- cgit v1.2.3 From 28e81afd92a6568ff78736b72c5257a86c0b9b91 Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 18 Nov 2008 08:03:35 +0000 Subject: GUI refactoring 1 git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@177 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/online/applet/AppletBKUWorker.java | 13 +- .../bku/online/applet/AppletHashDataDisplay.java | 24 +- .../at/gv/egiz/bku/online/applet/BKUApplet.java | 6 +- BKUApplet/src/test/resources/appletTest.html | 3 +- .../src/main/java/at/gv/egiz/bku/gui/BKUGUI.java | 6 +- .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 6 +- .../java/at/gv/egiz/bku/gui/BKUGUIFactory.java | 25 +- .../at/gv/egiz/bku/gui/DefaultHelpListener.java | 37 +- .../java/at/gv/egiz/bku/gui/HashDataViewer.java | 6 - .../main/java/at/gv/egiz/bku/gui/HelpViewer.java | 2 +- .../main/java/at/gv/egiz/bku/gui/SimpleGUI.java | 1165 +++++++++++--------- .../at/gv/egiz/bku/gui/Messages.properties | 2 +- .../at/gv/egiz/bku/gui/Messages_en.properties | 2 +- .../test/java/at/gv/egiz/bku/gui/BKUGUITest.java | 5 +- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 110 +- .../at/gv/egiz/bku/local/stal/BKUGuiProxy.java | 12 +- .../bku/local/stal/LocalSignRequestHandler.java | 2 +- .../at/gv/egiz/bku/local/stal/SMCCSTALFactory.java | 7 +- BKUOnline/src/main/webapp/HTTP-ohne.html | 2 +- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 81 -- 20 files changed, 793 insertions(+), 723 deletions(-) (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java index f862360b..b2f9f89c 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java @@ -192,18 +192,19 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { private void registerSignRequestHandler() throws MalformedURLException { String hashDataDisplayStyle = params.getAppletParameter(BKUApplet.HASHDATA_DISPLAY); - if (BKUApplet.HASHDATA_DISPLAY_INTERNAL.equals(hashDataDisplayStyle)) { - log.debug("register SignRequestHandler for STAL port " + BKUApplet.WSDL_URL); - AppletHashDataDisplay handler = new AppletHashDataDisplay(stalPort, sessionId, AppletHashDataDisplay.DISPLAY.applet); - addRequestHandler(SignRequest.class, handler); - } else if (BKUApplet.HASHDATA_DISPLAY_BROWSER.equals(hashDataDisplayStyle)) { +// if (BKUApplet.HASHDATA_DISPLAY_INTERNAL.equals(hashDataDisplayStyle)) { +// log.debug("register SignRequestHandler for STAL port " + BKUApplet.WSDL_URL); +// AppletHashDataDisplay handler = new AppletHashDataDisplay(stalPort, sessionId, AppletHashDataDisplay.DISPLAY.applet); +// addRequestHandler(SignRequest.class, handler); +// } else + if (BKUApplet.HASHDATA_DISPLAY_BROWSER.equals(hashDataDisplayStyle)) { URL hashDataURL = params.getURLParameter(BKUApplet.HASHDATA_URL, sessionId); log.debug("register SignRequestHandler for HashDataURL " + hashDataURL); addRequestHandler(SignRequest.class, new BrowserHashDataDisplay(ctx, hashDataURL)); } else { //BKUApplet.HASHDATA_DISPLAY_FRAME log.debug("register SignRequestHandler for STAL port " + BKUApplet.WSDL_URL); - AppletHashDataDisplay handler = new AppletHashDataDisplay(stalPort, sessionId, AppletHashDataDisplay.DISPLAY.frame); + AppletHashDataDisplay handler = new AppletHashDataDisplay(stalPort, sessionId); addRequestHandler(SignRequest.class, handler); } } diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java index 29a60f1d..ba502906 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java @@ -50,33 +50,32 @@ import java.security.NoSuchAlgorithmException; */ public class AppletHashDataDisplay extends SignRequestHandler { - public static enum DISPLAY { - applet, frame - } private static final Log log = LogFactory.getLog(AppletHashDataDisplay.class); protected STALPortType stalPort; protected String sessId; - protected DISPLAY display; - public AppletHashDataDisplay(STALPortType stalPort, String sessId, DISPLAY display) { + public AppletHashDataDisplay(STALPortType stalPort, String sessId) { if (stalPort == null || sessId == null) { throw new NullPointerException("STAL port must not be null"); } this.sessId = sessId; this.stalPort = stalPort; - this.display = display; } + /** + * TODO don't throw exceptions + * @param signedReferences + * @throws java.security.DigestException + * @throws java.lang.Exception + */ @Override public void displayHashDataInputs(List signedReferences) throws DigestException, Exception { List hdi = getHashDataInput(signedReferences); List verifiedHashDataInputs = verifyHashDataInput(signedReferences, hdi); - if (verifiedHashDataInputs.size() > 1) { - gui.showHashDataInputDialog(verifiedHashDataInputs, false, this, "ok"); - } else if (verifiedHashDataInputs.size() == 1) { - gui.showHashDataInputDialog(verifiedHashDataInputs, display==DISPLAY.frame, this, "ok"); + if (verifiedHashDataInputs.size() > 0) { + gui.showHashDataInputDialog(verifiedHashDataInputs, this, "ok"); } else { throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); } @@ -111,6 +110,11 @@ public class AppletHashDataDisplay extends SignRequestHandler { } } } + + if (request.getReference().size() < 1) { + log.error("No signature data (apart from any QualifyingProperties or a Manifest) for session " + sessId); + throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); + } if (log.isDebugEnabled()) { log.debug("WebService call GetHashDataInput for " + request.getReference().size() + " references in session " + sessId); diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java index 7963768e..5b45c8e1 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java @@ -53,7 +53,7 @@ public class BKUApplet extends JApplet implements AppletParameterProvider { public static final String BACKGROUND_PARAM = "Background"; public static final String REDIRECT_URL = "RedirectURL"; public static final String REDIRECT_TARGET = "RedirectTarget"; - public static final String HASHDATA_DISPLAY_INTERNAL = "internal"; +// public static final String HASHDATA_DISPLAY_INTERNAL = "internal"; public static final String HASHDATA_DISPLAY_BROWSER = "browser"; public static final String HASHDATA_DISPLAY_FRAME = "frame"; @@ -106,8 +106,8 @@ public class BKUApplet extends JApplet implements AppletParameterProvider { } log.debug("setting locale to " + getLocale()); - BKUGUIFacade gui = BKUGUIFactory.createGUI(guiStyle); - gui.init(getContentPane(), getLocale(), backgroundImgURL, helpListener); + BKUGUIFacade gui = BKUGUIFactory.createGUI(getContentPane(), getLocale(), guiStyle, backgroundImgURL, helpListener); +// gui.init(getContentPane(), getLocale(), BKUGUIFacade.Style.advanced, backgroundImgURL, helpListener); worker = new AppletBKUWorker(gui, getAppletContext(), this); } diff --git a/BKUApplet/src/test/resources/appletTest.html b/BKUApplet/src/test/resources/appletTest.html index eaf6376d..8204d0eb 100644 --- a/BKUApplet/src/test/resources/appletTest.html +++ b/BKUApplet/src/test/resources/appletTest.html @@ -21,7 +21,8 @@ archive="../BKUApplet-1.0-SNAPSHOT.jar, ../test-libs/commons-logging-1.1.1.jar , ../test-libs/iaik_jce_me4se-3.04.jar" width=300 height=200> - + + diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java index d661c71a..f68f2ece 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java @@ -87,8 +87,8 @@ public class BKUGUI implements BKUGUIFacade { * @param contentPane * @param localeString may be null */ - @Override - public void init(final Container contentPane, Locale locale, final URL background, ActionListener helpListener) { +// @Override + public void init(final Container contentPane, Locale locale, Style guiStyle, final URL background, ActionListener helpListener) { if (locale != null) { messages = ResourceBundle.getBundle(MESSAGES_BUNDLE, locale); @@ -814,7 +814,7 @@ public class BKUGUI implements BKUGUIFacade { } @Override - public void showHashDataInputDialog(final List signedReferences, boolean standalone, final ActionListener okListener, final String okCommand) { + public void showHashDataInputDialog(final List signedReferences, final ActionListener okListener, final String okCommand) { if (signedReferences == null) { showErrorDialog(messages.getString(ERR_NO_HASHDATA), new Object[] {"No SignedReferences provided"}, okListener, okCommand); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index 87982c79..2dbba730 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -91,7 +91,9 @@ public interface BKUGUIFacade { public static final String SAVE_HASHDATAINPUT_PREFIX = "save.hashdatainput.prefix"; public static final String ALT_HELP = "alt.help"; - public void init(Container contentPane, Locale locale, URL background, ActionListener helpListener); + public enum Style { simple, advanced }; + +// public void init(Container contentPane, Locale locale, Style guiStyle, URL background, ActionListener helpListener); /** * @@ -128,7 +130,7 @@ public interface BKUGUIFacade { * @param okListener * @param okCommand */ - public void showHashDataInputDialog(List signedReferences, boolean externalDisplay, ActionListener okListener, String okCommand); + public void showHashDataInputDialog(List signedReferences, ActionListener okListener, String okCommand); /** * TODO pull out from BKUGUIFacade. (or make this strictly an applet internal version) diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFactory.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFactory.java index 87676026..f4981614 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFactory.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFactory.java @@ -17,24 +17,29 @@ package at.gv.egiz.bku.gui; +import java.awt.Container; +import java.awt.event.ActionListener; +import java.net.URL; +import java.util.Locale; + public class BKUGUIFactory { public static final String SIMPLE_GUI = "simple"; public static final String ADVANCED_GUI = "advanced"; - private static BKUGUIFactory instance = new BKUGUIFactory(); +// private static BKUGUIFactory instance = new BKUGUIFactory(); - private BKUGUIFactory() { - } +// private BKUGUIFactory() { +// } +// +// protected BKUGUIFacade createNewGUI(Container contentPane, Locale locale, String style, URL background, ActionListener helpListener) { +// +// } - protected BKUGUIFacade createNewGUI(String style) { + public static BKUGUIFacade createGUI(Container contentPane, Locale locale, String style, URL background, ActionListener helpListener) { if (ADVANCED_GUI.equals(style)) { - return new BKUGUI(); + return new SimpleGUI(contentPane, locale, BKUGUIFacade.Style.advanced, background, helpListener); } - return new SimpleGUI(); - } - - public static BKUGUIFacade createGUI(String style) { - return instance.createNewGUI(style); + return new SimpleGUI(contentPane, locale, BKUGUIFacade.Style.simple, background, helpListener); } } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/DefaultHelpListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/DefaultHelpListener.java index ba968a48..f03bf158 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/DefaultHelpListener.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/DefaultHelpListener.java @@ -17,6 +17,7 @@ package at.gv.egiz.bku.gui; import java.applet.AppletContext; +import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.Locale; import javax.swing.SwingUtilities; @@ -29,34 +30,56 @@ public class DefaultHelpListener extends AbstractHelpListener { protected AppletContext ctx; + /** + * + * @param ctx open external links via applet context + * @param helpURL + * @param locale + */ public DefaultHelpListener(AppletContext ctx, URL helpURL, Locale locale) { super(helpURL, locale); this.ctx = ctx; } + /** + * external links in help document are not opened + * @param helpURL + * @param locale + */ public DefaultHelpListener(URL helpURL, Locale locale) { super(helpURL, locale); this.ctx = null; } + /** + * blocks until help viewer returns (is closed) + * @param helpURL + * @param helpTopic + */ @Override - public void showDocument(final URL helpURL, final String helpTopic) throws Exception { - log.debug("schedule help dialog"); - - SwingUtilities.invokeLater(new Runnable() { + public void showDocument(final URL helpURL, final String helpTopic) { +// try { + log.debug("schedule help dialog"); + +// SwingUtilities.invokeAndWait(new Runnable() { + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - + log.debug("show help dialog"); - + if (ctx == null) { HelpViewer.showHelpDialog(helpURL, helpTopic, messages); - } else { HelpViewer.showHelpDialog(ctx, helpURL, helpTopic, messages); } } }); +// } catch (InterruptedException ex) { +// log.error("Failed to display HelpViewer: " + ex.getMessage(), ex); +// } catch (InvocationTargetException ex) { +// log.error("Failed to display HelpViewer: " + ex.getMessage(), ex); +// } } } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java index 31887bde..7b77faeb 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java @@ -16,7 +16,6 @@ */ package at.gv.egiz.bku.gui; -import at.gv.egiz.bku.gui.html.RestrictedHTMLEditorKit; import at.gv.egiz.stal.HashDataInput; import java.awt.Component; import java.awt.Container; @@ -49,11 +48,6 @@ import javax.swing.JScrollPane; import javax.swing.LayoutStyle; import javax.swing.text.Document; import javax.swing.text.EditorKit; -import javax.swing.text.Element; -import javax.swing.text.ViewFactory; -import javax.swing.text.html.HTML; -import javax.swing.text.html.HTMLEditorKit; -import javax.swing.text.html.ImageView; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java index 173254e7..0fef3f75 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java @@ -105,7 +105,7 @@ public class HelpViewer extends JDialog JPanel helpPanel = createViewerPanel(viewerLabel, helpURL); JPanel buttonPanel = createButtonPanel(); - initContentPane(new Dimension(600, 400), helpPanel, buttonPanel); + initContentPane(new Dimension(600, 600), helpPanel, buttonPanel); pack(); if (frame != null) { setLocationRelativeTo(frame); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SimpleGUI.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SimpleGUI.java index bb568b75..d4d6efef 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SimpleGUI.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SimpleGUI.java @@ -32,6 +32,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.text.MessageFormat; import java.util.List; @@ -40,7 +41,6 @@ import java.util.ResourceBundle; import javax.swing.GroupLayout; import javax.swing.ImageIcon; import javax.swing.JButton; -import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JOptionPane; @@ -51,7 +51,6 @@ import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.LayoutStyle; import javax.swing.SwingUtilities; -import javax.swing.table.TableColumn; import javax.swing.table.TableModel; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -69,38 +68,60 @@ public class SimpleGUI implements BKUGUIFacade { protected Container contentPane; protected ResourceBundle messages; /** left and right side main panels */ -// protected JPanel iconPanel; + protected JPanel iconPanel; protected JPanel contentPanel; /** right side content panels and layouts */ -// protected JPanel headerPanel; + protected JPanel headerPanel; protected JPanel mainPanel; protected JPanel buttonPanel; /** right side fixed labels */ -// protected JLabel titleLabel; + protected JLabel titleLabel; protected JLabel helpLabel; /** remember the pinfield to return to worker */ protected JPasswordField pinField; protected int buttonSize; -// private static final int CHECKBOX_WIDTH = new JCheckBox().getPreferredSize().width; + /** gui style config (default 'simple') */ + protected boolean renderHeaderPanel = false; + protected boolean renderIconPanel = false; + protected boolean renderCancelButton = false; /** + * set contentPane + * init message bundle + * configure the style + * register the help listener + * create GUI (on event-dispatching thread) + * * @param contentPane - * @param localeString may be null + * @param locale + * @param guiStyle + * @param background + * @param helpListener */ - @Override - public void init(final Container contentPane, Locale locale, final URL background, ActionListener helpListener) { + public SimpleGUI(Container contentPane, Locale locale, Style guiStyle, URL background, ActionListener helpListener) { + this.contentPane = contentPane; - if (locale != null) { - messages = ResourceBundle.getBundle(MESSAGES_BUNDLE, locale); - } else { - messages = ResourceBundle.getBundle(MESSAGES_BUNDLE); - } + if (locale != null) { + messages = ResourceBundle.getBundle(MESSAGES_BUNDLE, locale); + } else { + messages = ResourceBundle.getBundle(MESSAGES_BUNDLE); + } + + if (guiStyle == Style.advanced) { + renderHeaderPanel = true; + renderIconPanel = false; + renderCancelButton = true; + } + + registerHelpListener(helpListener); + + createGUI(background); + } + + private void createGUI(final URL background) { - this.contentPane = contentPane; - registerHelpListener(helpListener); - try { log.debug("scheduling gui initialization"); @@ -112,21 +133,28 @@ public class SimpleGUI implements BKUGUIFacade { log.debug("initializing gui"); -// initIconPanel(); + if (renderIconPanel) { + initIconPanel(background); + initContentPanel(null); + } else { initContentPanel(background); - - GroupLayout layout = new GroupLayout(contentPane); - contentPane.setLayout(layout); + } + + GroupLayout layout = new GroupLayout(contentPane); + contentPane.setLayout(layout); + + if (renderIconPanel) { + layout.setHorizontalGroup(layout.createSequentialGroup() + .addComponent(iconPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); + layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(iconPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); + } else { layout.setHorizontalGroup(layout.createSequentialGroup().addComponent(contentPanel)); layout.setVerticalGroup(layout.createSequentialGroup().addComponent(contentPanel)); -// layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addGroup(layout.createSequentialGroup() -// .addComponent(iconPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) -// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) -// .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); -// layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addComponent(iconPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); + } } }); } catch (Exception ex) { @@ -134,119 +162,113 @@ public class SimpleGUI implements BKUGUIFacade { } } -// protected void initIconPanel() { -// iconPanel = new JPanel(); -// JLabel iconLabel = new JLabel(); -// iconLabel.setIcon(new ImageIcon(getClass().getResource(LOGO_RESOURCE))); // NOI18N -// -// GroupLayout iconPanelLayout = new GroupLayout(iconPanel); -// iconPanel.setLayout(iconPanelLayout); -// iconPanelLayout.setHorizontalGroup( -// iconPanelLayout.createSequentialGroup() -// .addContainerGap() -// .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, iconLabel.getPreferredSize().width, GroupLayout.PREFERRED_SIZE) -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); //); -// iconPanelLayout.setVerticalGroup( -// iconPanelLayout.createSequentialGroup() -// .addContainerGap() -// .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, iconLabel.getPreferredSize().height, GroupLayout.PREFERRED_SIZE) -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); //); -// } + protected void initIconPanel(URL background) { + if (background == null) { + background = getClass().getResource(DEFAULT_BACKGROUND); + } + if ("file".equals(background.getProtocol())) { + log.warn("file:// background images not permitted: " + background); + background = getClass().getResource(DEFAULT_BACKGROUND); + } + log.debug("loading icon panel background " + background); + + iconPanel = new JPanel(); + JLabel iconLabel = new JLabel(); + iconLabel.setIcon(new ImageIcon(background)); + + GroupLayout iconPanelLayout = new GroupLayout(iconPanel); + iconPanel.setLayout(iconPanelLayout); + iconPanelLayout.setHorizontalGroup( + iconPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); + // no gap here (contentPanel has containerGap) + iconPanelLayout.setVerticalGroup( + iconPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); + } protected void initContentPanel(URL background) { if (background == null) { - background = this.getClass().getResource(DEFAULT_BACKGROUND); + background = getClass().getResource(DEFAULT_BACKGROUND); } if ("file".equals(background.getProtocol())) { - log.warn("local background image not allowed: " + background); - background = this.getClass().getResource(DEFAULT_BACKGROUND); + log.warn("file:// background images not permitted: " + background); + background = getClass().getResource(DEFAULT_BACKGROUND); } log.debug("loading background " + background); contentPanel = new ImagePanel(background); -// contentPanel.setBorder(new TitledBorder("content")); - -// headerPanel = new JPanel(); -// headerPanel.setOpaque(false); - mainPanel = new JPanel(); - mainPanel.setOpaque(false); - buttonPanel = new JPanel(); - buttonPanel.setOpaque(false); - -// headerPanel.setBorder(new TitledBorder("header")); -// mainPanel.setBorder(new TitledBorder("main")); -// buttonPanel.setBorder(new TitledBorder("button")); - -// titleLabel = new JLabel(); -// titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() | -// java.awt.Font.BOLD, titleLabel.getFont().getSize() + 2)); - - helpLabel = new JLabel(); - helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG))); - helpLabel.getAccessibleContext().setAccessibleName(messages.getString(ALT_HELP)); - helpLabel.addMouseListener(helpListener); - helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - - JButton b = new JButton(); -// b.setText(messages.getString(BUTTON_CANCEL)); -// if (b.getPreferredSize().width > buttonSize) -// buttonSize = b.getPreferredSize().width; - b.setText(messages.getString(BUTTON_OK)); - if (b.getPreferredSize().width > buttonSize) - buttonSize = b.getPreferredSize().width; - b.setText(messages.getString(BUTTON_SIGN)); - if (b.getPreferredSize().width > buttonSize) - buttonSize = b.getPreferredSize().width; - b.setText(messages.getString(BUTTON_BACK)); - if (b.getPreferredSize().width > buttonSize) - buttonSize = b.getPreferredSize().width; -// b.setText(messages.getString(BUTTON_SAVE)); -// if (b.getPreferredSize().width > buttonSize) -// buttonSize = b.getPreferredSize().width; - -// if (cancelButton.getPreferredSize().width > buttonSize) -// buttonSize = cancelButton.getPreferredSize().width; -// if (signButton.getPreferredSize().width > buttonSize) -// buttonSize = signButton.getPreferredSize().width; -// if (backButton.getPreferredSize().width > buttonSize) -// buttonSize = backButton.getPreferredSize().width; -// if (saveButton.getPreferredSize().width > buttonSize) -// buttonSize = saveButton.getPreferredSize().width; + mainPanel = new JPanel(); + mainPanel.setOpaque(false); + buttonPanel = new JPanel(); + buttonPanel.setOpaque(false); + helpLabel = new JLabel(); + helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG))); + helpLabel.getAccessibleContext().setAccessibleName(messages.getString(ALT_HELP)); + helpLabel.addMouseListener(helpListener); + helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + + buttonSize = initButtonSize(messages, renderCancelButton); -// GroupLayout headerPanelLayout = new GroupLayout(headerPanel); -// headerPanel.setLayout(headerPanelLayout); -// -// headerPanelLayout.setHorizontalGroup( -// headerPanelLayout.createSequentialGroup() -// .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); -// headerPanelLayout.setVerticalGroup( -// headerPanelLayout.createSequentialGroup() -// .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); - - - GroupLayout contentPanelLayout = new GroupLayout(contentPanel); - contentPanel.setLayout(contentPanelLayout); - - contentPanelLayout.setHorizontalGroup( - contentPanelLayout.createSequentialGroup() - .addContainerGap() - .addGroup( - contentPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap()); - contentPanelLayout.setVerticalGroup( - contentPanelLayout.createSequentialGroup() - .addContainerGap() -// .addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) -// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) //, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap()); + if (renderHeaderPanel) { + headerPanel = new JPanel(); + headerPanel.setOpaque(false); + + titleLabel = new JLabel(); + titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() | + java.awt.Font.BOLD, titleLabel.getFont().getSize() + 2)); + + GroupLayout headerPanelLayout = new GroupLayout(headerPanel); + headerPanel.setLayout(headerPanelLayout); + + headerPanelLayout.setHorizontalGroup( + headerPanelLayout.createSequentialGroup() + .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)); + headerPanelLayout.setVerticalGroup( + headerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) + .addComponent(helpLabel)); + } + + GroupLayout contentPanelLayout = new GroupLayout(contentPanel); + contentPanel.setLayout(contentPanelLayout); + + GroupLayout.ParallelGroup horizontalContentInner = contentPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + if (renderHeaderPanel) { + horizontalContentInner + .addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); + } + horizontalContentInner + .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); + GroupLayout.SequentialGroup horizontalContentOuter = contentPanelLayout.createSequentialGroup(); + if (!renderIconPanel) { + horizontalContentOuter + .addContainerGap(); + } + horizontalContentOuter + .addGroup(horizontalContentInner) + .addContainerGap(); + contentPanelLayout.setHorizontalGroup(horizontalContentOuter); + + GroupLayout.SequentialGroup verticalContent = contentPanelLayout.createSequentialGroup(); + verticalContent.addContainerGap(); + if (renderHeaderPanel) { + verticalContent.addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); + } + verticalContent.addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addContainerGap(); + contentPanelLayout.setVerticalGroup(verticalContent); } @Override @@ -269,26 +291,35 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); -// titleLabel.setText(messages.getString(TITLE_WELCOME)); - helpListener.setHelpTopic(HELP_WELCOME); JLabel welcomeMsgLabel = new JLabel(); welcomeMsgLabel.setFont(welcomeMsgLabel.getFont().deriveFont(welcomeMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - welcomeMsgLabel.setText(messages.getString(TITLE_WELCOME)); - + + if (renderHeaderPanel) { + titleLabel.setText(messages.getString(TITLE_WELCOME)); + welcomeMsgLabel.setText(messages.getString(MESSAGE_WAIT)); + } else { + welcomeMsgLabel.setText(messages.getString(TITLE_WELCOME)); + } + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(welcomeMsgLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(welcomeMsgLabel) - .addComponent(helpLabel)); + GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(welcomeMsgLabel); + GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(welcomeMsgLabel); + if (!renderHeaderPanel) { + messageHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + messageVertical + .addComponent(helpLabel); + } + + mainPanelLayout.setHorizontalGroup(messageHorizontal); + mainPanelLayout.setVerticalGroup(messageVertical); contentPanel.validate(); @@ -311,8 +342,10 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); -// titleLabel.setText(messages.getString(TITLE_INSERTCARD)); - + if (renderHeaderPanel) { + titleLabel.setText(messages.getString(TITLE_INSERTCARD)); + } + helpListener.setHelpTopic(HELP_INSERTCARD); JLabel insertCardMsgLabel = new JLabel(); @@ -322,31 +355,39 @@ public class SimpleGUI implements BKUGUIFacade { GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(insertCardMsgLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(insertCardMsgLabel) - .addComponent(helpLabel)); + GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(insertCardMsgLabel); + GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup() + .addComponent(insertCardMsgLabel); -// JButton cancelButton = new JButton(); -// cancelButton.setText(messages.getString(BUTTON_CANCEL)); -// cancelButton.addActionListener(cancelListener); -// cancelButton.setActionCommand(cancelCommand); -// -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// buttonPanelLayout.setHorizontalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); -// buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addComponent(cancelButton)); + if (!renderHeaderPanel) { + messageHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + messageVertical + .addComponent(helpLabel); + } + + mainPanelLayout.setHorizontalGroup(messageHorizontal); + mainPanelLayout.setVerticalGroup(messageVertical); + + if (renderCancelButton) { + JButton cancelButton = new JButton(); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); + cancelButton.addActionListener(cancelListener); + cancelButton.setActionCommand(cancelCommand); + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + buttonPanelLayout.setHorizontalGroup( + buttonPanelLayout.createSequentialGroup() + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); + buttonPanelLayout.setVerticalGroup( + buttonPanelLayout.createSequentialGroup() + .addComponent(cancelButton)); + } contentPanel.validate(); } @@ -373,48 +414,89 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); -// titleLabel.setText(messages.getString(TITLE_CARD_NOT_SUPPORTED)); + JLabel insertCardMsgLabel = new JLabel(); + insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + + if (renderHeaderPanel) { + titleLabel.setText(messages.getString(TITLE_CARD_NOT_SUPPORTED)); + insertCardMsgLabel.setText(messages.getString(MESSAGE_INSERTCARD)); + } else { + insertCardMsgLabel.setText(messages.getString(TITLE_CARD_NOT_SUPPORTED)); + } helpListener.setHelpTopic(HELP_CARDNOTSUPPORTED); - JLabel insertCardMsgLabel = new JLabel(); - insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - insertCardMsgLabel.setText(messages.getString(TITLE_CARD_NOT_SUPPORTED)); + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(insertCardMsgLabel); + GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(insertCardMsgLabel); + if (!renderHeaderPanel) { + messageHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + messageVertical + .addComponent(helpLabel); + } + + mainPanelLayout.setHorizontalGroup(messageHorizontal); + mainPanelLayout.setVerticalGroup(messageVertical); + + if (renderCancelButton) { + JButton cancelButton = new JButton(); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); + cancelButton.addActionListener(cancelListener); + cancelButton.setActionCommand(cancelCommand); - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(insertCardMsgLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(insertCardMsgLabel) - .addComponent(helpLabel)); - -// JButton cancelButton = new JButton(); -// cancelButton.setText(messages.getString(BUTTON_CANCEL)); -// cancelButton.addActionListener(cancelListener); -// cancelButton.setActionCommand(cancelCommand); -// -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// buttonPanelLayout.setHorizontalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); -// buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addComponent(cancelButton)); - - contentPanel.validate(); + buttonPanelLayout.setHorizontalGroup( + buttonPanelLayout.createSequentialGroup() + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); + buttonPanelLayout.setVerticalGroup( + buttonPanelLayout.createSequentialGroup() + .addComponent(cancelButton)); + } + + contentPanel.validate(); } }); } + private static int initButtonSize(ResourceBundle messages, boolean renderCancelButton) { + + int buttonSize = 0; + + JButton b = new JButton(); + b.setText(messages.getString(BUTTON_OK)); + if (b.getPreferredSize().width > buttonSize) { + buttonSize = b.getPreferredSize().width; + } + b.setText(messages.getString(BUTTON_SIGN)); + if (b.getPreferredSize().width > buttonSize) { + buttonSize = b.getPreferredSize().width; + } + b.setText(messages.getString(BUTTON_BACK)); + if (b.getPreferredSize().width > buttonSize) { + buttonSize = b.getPreferredSize().width; + } + b.setText(messages.getString(BUTTON_SAVE)); + if (b.getPreferredSize().width > buttonSize) { + buttonSize = b.getPreferredSize().width; + } + if (renderCancelButton) { + b.setText(messages.getString(BUTTON_CANCEL)); + if (b.getPreferredSize().width > buttonSize) { + buttonSize = b.getPreferredSize().width; + } + } + return buttonSize; + } + private void showCardPINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener okListener, final String okCommand, final ActionListener cancelListener, final String cancelCommand) { log.debug("scheduling card-pin dialog"); @@ -429,17 +511,14 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); -// if (numRetries < 0) { -// String cardpinTitle = messages.getString(TITLE_CARDPIN); -// titleLabel.setText(MessageFormat.format(cardpinTitle, new Object[]{pinSpec.getLocalizedName()})); -// } else { -// titleLabel.setText(messages.getString(TITLE_RETRY)); -// } - -// JButton cancelButton = new JButton(); -// cancelButton.setText(messages.getString(BUTTON_CANCEL)); -// cancelButton.setActionCommand(cancelCommand); -// cancelButton.addActionListener(cancelListener); + if (renderHeaderPanel) { + if (numRetries < 0) { + String cardpinTitle = messages.getString(TITLE_CARDPIN); + titleLabel.setText(MessageFormat.format(cardpinTitle, new Object[]{pinSpec.getLocalizedName()})); + } else { + titleLabel.setText(messages.getString(TITLE_RETRY)); + } + } JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -492,55 +571,73 @@ public class SimpleGUI implements BKUGUIFacade { GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(infoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addGroup(mainPanelLayout.createSequentialGroup() + GroupLayout.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + GroupLayout.SequentialGroup pinHorizontal = mainPanelLayout.createSequentialGroup() .addComponent(cardPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) //)) - .addComponent(pinsizeLabel)))); - - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(infoLabel) - .addComponent(helpLabel)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(cardPinLabel) - .addComponent(pinField)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinsizeLabel)); + .addComponent(pinsizeLabel)); + + GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup(); + + if (!renderHeaderPanel) { + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(infoLabel) //, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); //, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + mainHorizontal + .addGroup(infoHorizontal) + .addGroup(pinHorizontal); + GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(infoLabel) + .addComponent(helpLabel); + mainVertical + .addGroup(infoVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); + } else { + mainHorizontal + .addGroup(pinHorizontal); + } + mainVertical + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(cardPinLabel) + .addComponent(pinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel); + + mainPanelLayout.setHorizontalGroup(mainHorizontal); + mainPanelLayout.setVerticalGroup(mainVertical); + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); buttonPanel.setLayout(buttonPanelLayout); - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(okButton)); - -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// buttonPanelLayout.setHorizontalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) -// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) -// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); -// buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) -// .addComponent(okButton) -// .addComponent(cancelButton)); + .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + GroupLayout.Group buttonVertical; + + if (renderCancelButton) { + JButton cancelButton = new JButton(); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); + cancelButton.setActionCommand(cancelCommand); + cancelButton.addActionListener(cancelListener); + + buttonHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(okButton) + .addComponent(cancelButton); + } else { + buttonVertical = buttonPanelLayout.createSequentialGroup() + .addComponent(okButton); + } + + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); + buttonPanelLayout.setVerticalGroup(buttonVertical); pinField.requestFocusInWindow(); contentPanel.validate(); @@ -583,16 +680,13 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); -// if (numRetries < 0) { -// titleLabel.setText(messages.getString(TITLE_SIGN)); -// } else { -// titleLabel.setText(messages.getString(TITLE_RETRY)); -// } - -// JButton cancelButton = new JButton(); -// cancelButton.setText(messages.getString(BUTTON_CANCEL)); -// cancelButton.setActionCommand(cancelCommand); -// cancelButton.addActionListener(cancelListener); + if (renderHeaderPanel) { + if (numRetries < 0) { + titleLabel.setText(messages.getString(TITLE_SIGN)); + } else { + titleLabel.setText(messages.getString(TITLE_RETRY)); + } + } JButton signButton = new JButton(); signButton.setFont(signButton.getFont().deriveFont(signButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -653,13 +747,23 @@ public class SimpleGUI implements BKUGUIFacade { GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(infoLabel); + GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(infoLabel); + + if (!renderHeaderPanel) { + infoHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); //, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); + infoVertical + .addComponent(helpLabel); + } mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(infoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addGroup(infoHorizontal) .addGroup(mainPanelLayout.createSequentialGroup() .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) @@ -669,9 +773,7 @@ public class SimpleGUI implements BKUGUIFacade { mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(infoLabel) - .addComponent(helpLabel)) + .addGroup(infoVertical) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(signPinLabel) @@ -682,27 +784,31 @@ public class SimpleGUI implements BKUGUIFacade { GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); buttonPanel.setLayout(buttonPanelLayout); - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(signButton)); - -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// buttonPanelLayout.setHorizontalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) -// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) -// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); -// buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) -// .addComponent(signButton) -// .addComponent(cancelButton)); + .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + GroupLayout.Group buttonVertical; + + if (renderCancelButton) { + JButton cancelButton = new JButton(); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); + cancelButton.setActionCommand(cancelCommand); + cancelButton.addActionListener(cancelListener); + + buttonHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + + buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(signButton) + .addComponent(cancelButton); + } else { + buttonVertical = buttonPanelLayout.createSequentialGroup() + .addComponent(signButton); + } + + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); + buttonPanelLayout.setVerticalGroup(buttonVertical); pinField.requestFocusInWindow(); contentPanel.validate(); @@ -726,15 +832,12 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); -// titleLabel.setText(messages.getString(TITLE_ERROR)); + if (renderHeaderPanel) { + titleLabel.setText(messages.getString(TITLE_ERROR)); + } helpListener.setHelpTopic(errorMsgKey); - JLabel errorTitleLabel = new JLabel(); - errorTitleLabel.setFont(errorTitleLabel.getFont().deriveFont(errorTitleLabel.getFont().getStyle() | java.awt.Font.BOLD)); - errorTitleLabel.setText(messages.getString(TITLE_ERROR)); - errorTitleLabel.setForeground(ERROR_COLOR); - String errorMsgPattern = messages.getString(errorMsgKey); String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); @@ -745,19 +848,30 @@ public class SimpleGUI implements BKUGUIFacade { GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(errorTitleLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)) - .addComponent(errorMsgLabel)); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(errorTitleLabel) - .addComponent(helpLabel)) - .addComponent(errorMsgLabel)); + GroupLayout.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup(); + + if (!renderHeaderPanel) { + JLabel errorTitleLabel = new JLabel(); + errorTitleLabel.setFont(errorTitleLabel.getFont().deriveFont(errorTitleLabel.getFont().getStyle() | java.awt.Font.BOLD)); + errorTitleLabel.setText(messages.getString(TITLE_ERROR)); + errorTitleLabel.setForeground(ERROR_COLOR); + + mainHorizontal + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(errorTitleLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)); + mainVertical + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(errorTitleLabel) + .addComponent(helpLabel)); + } + + mainPanelLayout.setHorizontalGroup(mainHorizontal + .addComponent(errorMsgLabel)); + mainPanelLayout.setVerticalGroup(mainVertical + .addComponent(errorMsgLabel)); JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -796,15 +910,12 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); -// titleLabel.setText(messages.getString(TITLE_ERROR)); + if (renderHeaderPanel) { + titleLabel.setText(messages.getString(TITLE_ERROR)); + } helpListener.setHelpTopic(errorMsgKey); - JLabel errorTitleLabel = new JLabel(); - errorTitleLabel.setFont(errorTitleLabel.getFont().deriveFont(errorTitleLabel.getFont().getStyle() | java.awt.Font.BOLD)); - errorTitleLabel.setText(messages.getString(TITLE_ERROR)); - errorTitleLabel.setForeground(ERROR_COLOR); - String errorMsgPattern = messages.getString(errorMsgKey); String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); @@ -815,20 +926,32 @@ public class SimpleGUI implements BKUGUIFacade { GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + + GroupLayout.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup(); + + if (!renderHeaderPanel) { + JLabel errorTitleLabel = new JLabel(); + errorTitleLabel.setFont(errorTitleLabel.getFont().deriveFont(errorTitleLabel.getFont().getStyle() | java.awt.Font.BOLD)); + errorTitleLabel.setText(messages.getString(TITLE_ERROR)); + errorTitleLabel.setForeground(ERROR_COLOR); + + mainHorizontal .addGroup(mainPanelLayout.createSequentialGroup() .addComponent(errorTitleLabel) .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)) - .addComponent(errorMsgLabel)); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() + .addComponent(helpLabel)); + mainVertical .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(errorTitleLabel) - .addComponent(helpLabel)) - .addComponent(errorMsgLabel)); + .addComponent(helpLabel)); + } + mainPanelLayout.setHorizontalGroup(mainHorizontal + .addComponent(errorMsgLabel)); + mainPanelLayout.setVerticalGroup(mainVertical + .addComponent(errorMsgLabel)); + contentPanel.validate(); } }); @@ -849,8 +972,10 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); -// titleLabel.setText(messages.getString(TITLE_WAIT)); - + if (renderHeaderPanel) { + titleLabel.setText(messages.getString(TITLE_WAIT)); + } + helpListener.setHelpTopic(HELP_WAIT); JLabel waitMsgLabel = new JLabel(); @@ -864,15 +989,20 @@ public class SimpleGUI implements BKUGUIFacade { GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(waitMsgLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(waitMsgLabel) - .addComponent(helpLabel)); + GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(waitMsgLabel); + GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(waitMsgLabel); + + if (!renderHeaderPanel) { + messageHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + messageVertical + .addComponent(helpLabel); + } + mainPanelLayout.setHorizontalGroup(messageHorizontal); + mainPanelLayout.setVerticalGroup(messageVertical); contentPanel.validate(); } @@ -887,50 +1017,58 @@ public class SimpleGUI implements BKUGUIFacade { return null; } + /** + * TODO handle multiple references in HashDataViewer + * @param signedReferences + * @param okListener + * @param okCommand + */ @Override - public void showHashDataInputDialog(final List signedReferences, boolean standalone, final ActionListener okListener, final String okCommand) { + public void showHashDataInputDialog(final List signedReferences, final ActionListener okListener, final String okCommand) { if (signedReferences == null) { showErrorDialog(messages.getString(ERR_NO_HASHDATA), new Object[] {"No SignedReferences provided"}, okListener, okCommand); + return; } + ActionListener saveHashDataListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + showSaveHashDataInputDialog(signedReferences, okListener, okCommand); + } + }; + if (signedReferences.size() == 1) { - if (standalone) { - ActionListener saveHashDataListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - showSaveHashDataInputDialog(signedReferences, okListener, okCommand); - } - }; - showHashDataViewer(signedReferences, saveHashDataListener, "save"); +// if (standalone) { - } else { - if ("text/plain".equals(signedReferences.get(0).getMimeType())) { - - ActionListener saveHashDataListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - showSaveHashDataInputDialog(signedReferences, okListener, okCommand); - } - }; - - try { - String hashDataText = getText(signedReferences.get(0)); - showPlainTextHashDataInputDialog(hashDataText, saveHashDataListener, "save", okListener, okCommand); - } catch (IOException ex) { - showErrorDialog(messages.getString(ERR_NO_HASHDATA), new Object[] {ex.getMessage()}, okListener, okCommand); - } + showHashDataViewer(signedReferences, saveHashDataListener, "save"); - } else { - showSaveHashDataInputDialog(signedReferences, okListener, okCommand); - } - } +// } else { +// if ("text/plain".equals(signedReferences.get(0).getMimeType())) { +// +// ActionListener saveHashDataListener = new ActionListener() { +// +// @Override +// public void actionPerformed(ActionEvent e) { +// showSaveHashDataInputDialog(signedReferences, okListener, okCommand); +// } +// }; +// +// try { +// String hashDataText = getText(signedReferences.get(0)); +// showPlainTextHashDataInputDialog(hashDataText, saveHashDataListener, "save", okListener, okCommand); +// } catch (IOException ex) { +// showErrorDialog(messages.getString(ERR_NO_HASHDATA), new Object[] {ex.getMessage()}, okListener, okCommand); +// } +// +// } else { +// showSaveHashDataInputDialog(signedReferences, okListener, okCommand); +// } +// } } else { - SimpleHashDataTableModel tableModel = new SimpleHashDataTableModel(signedReferences); // final HashDataTableModel tableModel = new HashDataTableModel(signedReferences); // // ActionListener saveHashDataListener = new ActionListener() { @@ -940,128 +1078,112 @@ public class SimpleGUI implements BKUGUIFacade { // showSaveHashDataInputDialog(tableModel.getSelectedHashData(), okListener, okCommand); // } // }; - showMultipleHashDataInputDialog(tableModel, okListener, okCommand); + + SimpleHashDataTableModel tableModel = new SimpleHashDataTableModel(signedReferences); + showMultipleHashDataInputDialog(tableModel, okListener, okCommand, saveHashDataListener, "save"); } } /** - * TODO + * blocks until dialog returns (is closed) * @param hashDataText * @param saveListener * @param saveCommand */ private void showHashDataViewer(final List signedReferences, final ActionListener saveListener, final String saveCommand) { - log.debug("scheduling plaintext hashdatainput dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show plaintext hashdatainput dialog"); - - ActionListener l = helpListener.getActionListener(); - HashDataViewer.showHashDataInput(contentPane, signedReferences, messages, saveListener, saveCommand, l); - } - }); - } - - private void showPlainTextHashDataInputDialog(final String hashDataText, final ActionListener saveListener, final String saveCommand, final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling plaintext hashdatainput dialog"); - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show plaintext hashdatainput dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - -// titleLabel.setText(messages.getString(TITLE_HASHDATA)); - - helpListener.setHelpTopic(HELP_HASHDATA); - - JLabel refIdLabel = new JLabel(); - refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - refIdLabel.setText(messages.getString(MESSAGE_HASHDATA)); //MessageFormat.format(refIdLabelPattern, new Object[]{refId})); - - JTextArea hashDataTextArea = new JTextArea(hashDataText); - hashDataTextArea.setEditable(false); -// hashDataTextArea.setColumns(1); -// hashDataTextArea.setRows(1); - hashDataTextArea.setFont(new Font(HASHDATA_FONT, hashDataTextArea.getFont().getStyle(), hashDataTextArea.getFont().getSize())); -// hashDataScrollPane.setViewportView(hashDataTextArea); -// hashDataScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); //HORIZONTAL_SCROLLBAR_NEVER); - hashDataTextArea.setLineWrap(true); - hashDataTextArea.setWrapStyleWord(true); - - JScrollPane hashDataScrollPane = new JScrollPane(hashDataTextArea); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(refIdLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)) - .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); - - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(refIdLabel) - .addComponent(helpLabel)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); - - JButton backButton = new JButton(); - backButton.setFont(backButton.getFont().deriveFont(backButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - backButton.setText(messages.getString(BUTTON_BACK)); - backButton.setActionCommand(cancelCommand); - backButton.addActionListener(cancelListener); + try { + log.debug("scheduling plaintext hashdatainput dialog"); -// JButton saveButton = new JButton(); -// saveButton.setText(messages.getString(BUTTON_SAVE)); -// saveButton.setActionCommand(saveCommand); -// saveButton.addActionListener(saveListener); + SwingUtilities.invokeAndWait(new Runnable() { - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); + @Override + public void run() { - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(backButton)); + log.debug("show plaintext hashdatainput dialog"); + ActionListener l = helpListener.getActionListener(); + HashDataViewer.showHashDataInput(contentPane, signedReferences, messages, saveListener, saveCommand, l); + } + }); + + } catch (InterruptedException ex) { + log.error("Failed to display HashDataViewer: " + ex.getMessage()); + } catch (InvocationTargetException ex) { + log.error("Failed to display HashDataViewer: " + ex.getMessage()); + } + } + +// private void showPlainTextHashDataInputDialog(final String hashDataText, final ActionListener saveListener, final String saveCommand, final ActionListener cancelListener, final String cancelCommand) { +// +// log.debug("scheduling plaintext hashdatainput dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show plaintext hashdatainput dialog"); +// +// mainPanel.removeAll(); +// buttonPanel.removeAll(); +// +// helpListener.setHelpTopic(HELP_HASHDATA); +// +// JLabel refIdLabel = new JLabel(); +// refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +// refIdLabel.setText(messages.getString(MESSAGE_HASHDATA)); //MessageFormat.format(refIdLabelPattern, new Object[]{refId})); +// +// JTextArea hashDataTextArea = new JTextArea(hashDataText); +// hashDataTextArea.setEditable(false); +// hashDataTextArea.setFont(new Font(HASHDATA_FONT, hashDataTextArea.getFont().getStyle(), hashDataTextArea.getFont().getSize())); +// hashDataTextArea.setLineWrap(true); +// hashDataTextArea.setWrapStyleWord(true); +// +// JScrollPane hashDataScrollPane = new JScrollPane(hashDataTextArea); +// +// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +// mainPanel.setLayout(mainPanelLayout); +// +// mainPanelLayout.setHorizontalGroup( +// mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +// .addGroup(mainPanelLayout.createSequentialGroup() +// .addComponent(refIdLabel) +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(helpLabel)) +// .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); +// +// mainPanelLayout.setVerticalGroup( +// mainPanelLayout.createSequentialGroup() +// .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +// .addComponent(refIdLabel) +// .addComponent(helpLabel)) +// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +// .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); +// +// JButton backButton = new JButton(); +// backButton.setFont(backButton.getFont().deriveFont(backButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +// backButton.setText(messages.getString(BUTTON_BACK)); +// backButton.setActionCommand(cancelCommand); +// backButton.addActionListener(cancelListener); +// // GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); // buttonPanel.setLayout(buttonPanelLayout); // // buttonPanelLayout.setHorizontalGroup( // buttonPanelLayout.createSequentialGroup() // .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) -// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) // .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); // buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) -// .addComponent(saveButton) -// .addComponent(backButton)); - - contentPanel.validate(); - } - }); - } +// buttonPanelLayout.createSequentialGroup() +// .addComponent(backButton)); +// +// contentPanel.validate(); +// } +// }); +// } - private void showMultipleHashDataInputDialog(final TableModel signedReferences, final ActionListener cancelListener, final String cancelCommand) { -// , final ActionListener saveListener, final String saveCommand + private void showMultipleHashDataInputDialog(final TableModel signedReferences, final ActionListener cancelListener, final String cancelCommand, final ActionListener saveListener, final String saveCommand) { log.debug("scheduling multiple hashdatainput dialog"); @@ -1075,8 +1197,10 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); -// titleLabel.setText(messages.getString(TITLE_HASHDATA)); - + if (renderHeaderPanel) { + titleLabel.setText(messages.getString(TITLE_HASHDATA)); + } + helpListener.setHelpTopic(HELP_HASHDATALIST); JLabel refIdLabel = new JLabel(); @@ -1124,36 +1248,31 @@ public class SimpleGUI implements BKUGUIFacade { backButton.setActionCommand(cancelCommand); backButton.addActionListener(cancelListener); -// JButton saveButton = new JButton(); -// saveButton.setText(messages.getString(BUTTON_SAVE)); -// saveButton.setActionCommand(saveCommand); -// saveButton.addActionListener(saveListener); - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); buttonPanel.setLayout(buttonPanelLayout); - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(backButton)); - - -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// buttonPanelLayout.setHorizontalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) -// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) -// .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); -// buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) -// .addComponent(saveButton) -// .addComponent(backButton)); + .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + GroupLayout.ParallelGroup buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(backButton); + + if (renderCancelButton) { + //render save button + JButton saveButton = new JButton(); + saveButton.setText(messages.getString(BUTTON_SAVE)); + saveButton.setActionCommand(saveCommand); + saveButton.addActionListener(saveListener); + + buttonHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + buttonVertical + .addComponent(saveButton); + } + + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); + buttonPanelLayout.setVerticalGroup(buttonVertical); contentPanel.validate(); } @@ -1243,36 +1362,36 @@ public class SimpleGUI implements BKUGUIFacade { }); } - private static String getText(HashDataInput hdi) throws IOException { - ByteArrayOutputStream baos = null; - try { - InputStream hashDataIS = hdi.getHashDataInput(); - if (hashDataIS == null) { - log.error("No HashDataInput stream for reference " + hdi.getReferenceId()); - return null; - } else { - baos = new ByteArrayOutputStream(hashDataIS.available()); - int c; - while ((c = hashDataIS.read()) != -1) { - baos.write(c); - } - String encoding = hdi.getEncoding(); - if (encoding == null) { - //default for URL-encoded - encoding = "UTF-8"; - } - return baos.toString(encoding); - } - } catch (IOException ex) { - log.error("Failed to read HashDataInput for reference " + hdi.getReferenceId() + ": " + ex.getMessage()); - throw ex; - } finally { - try { - baos.close(); - } catch (IOException ex) { - } - } - } +// private static String getText(HashDataInput hdi) throws IOException { +// ByteArrayOutputStream baos = null; +// try { +// InputStream hashDataIS = hdi.getHashDataInput(); +// if (hashDataIS == null) { +// log.error("No HashDataInput stream for reference " + hdi.getReferenceId()); +// return null; +// } else { +// baos = new ByteArrayOutputStream(hashDataIS.available()); +// int c; +// while ((c = hashDataIS.read()) != -1) { +// baos.write(c); +// } +// String encoding = hdi.getEncoding(); +// if (encoding == null) { +// //default for URL-encoded +// encoding = "UTF-8"; +// } +// return baos.toString(encoding); +// } +// } catch (IOException ex) { +// log.error("Failed to read HashDataInput for reference " + hdi.getReferenceId() + ": " + ex.getMessage()); +// throw ex; +// } finally { +// try { +// baos.close(); +// } catch (IOException ex) { +// } +// } +// } private void registerHelpListener(ActionListener helpListener) { if (helpListener != null) { diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 5f62c05a..b5a74ac1 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -14,7 +14,7 @@ # limitations under the License. title.welcome=Willkommen -title.insertcard=Bitte B\u00FCrgerkarte in den Kartenleser stecken +title.insertcard=Keine B\u00FCrgerkarte gefunden title.cardnotsupported=Die Karte wird nicht unterst\u00FCtzt title.cardpin={0} eingeben title.sign=Signatur erstellen diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties index d963fd5f..94464982 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties @@ -14,7 +14,7 @@ # limitations under the License. title.welcome=Welcome -title.insertcard=Please insert your citizen-card into the reader +title.insertcard=No citizen-card found title.cardnotsupported=This card is not supported title.cardpin=Enter {0} title.sign=Create signature diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java index c32a237a..b57e1923 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java @@ -32,15 +32,16 @@ import org.junit.Test; * * @author clemens */ +@Ignore public class BKUGUITest { - @Ignore + @Test public void testBKUGUI() { JFrame testFrame = new JFrame("BKUGUITest"); BKUGUI gui = new BKUGUI(); Container contentPane = testFrame.getContentPane(); contentPane.setPreferredSize(new Dimension(380, 150)); - gui.init(contentPane, null, null, null); + gui.init(contentPane, null, BKUGUIFacade.Style.advanced, null, null); BKUGUIWorker worker = new BKUGUIWorker(); worker.init(gui); testFrame.pack(); diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index af1368e5..e4936067 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -43,7 +43,7 @@ public class BKUGUIWorker implements Runnable { @Override public void run() { - try { +// try { final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN"); @@ -176,7 +176,7 @@ public class BKUGUIWorker implements Runnable { // signedRefs.add(signedRef4); // signedRefs.add(signedRef4); // signedRefs = Collections.singletonList(signedRef1); - gui.showHashDataInputDialog(signedRefs, true, returnListener, "return"); + gui.showHashDataInputDialog(signedRefs, returnListener, "return"); } }; @@ -184,64 +184,64 @@ public class BKUGUIWorker implements Runnable { gui.showWelcomeDialog(); - Thread.sleep(2000); - - gui.showWaitDialog(null); - - Thread.sleep(1000); - - gui.showWaitDialog("test"); - - Thread.sleep(1000); - - - gui.showInsertCardDialog(cancelListener, "cancel"); - - Thread.sleep(2000); - - gui.showCardNotSupportedDialog(cancelListener, "cancel"); - - Thread.sleep(2000); - - PINSpec cardPinSpec = new PINSpec(4, 4, "[0-9]", "Karten-PIN"); - - gui.showCardPINDialog(cardPinSpec, okListener, "ok", cancelListener, "cancel"); - - Thread.sleep(2000); - - gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); - - Thread.sleep(4000); - - gui.showSignaturePINRetryDialog(signPinSpec, 2, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); - - Thread.sleep(2000); - - gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {"Testfehler"}, null, null); - - Thread.sleep(2000); - - gui.showErrorDialog("error.test", new Object[] {"Testfehler", "noch ein TestFehler"}); - - Thread.sleep(2000); - - gui.showErrorDialog("error.no.hashdata", null); - - Thread.sleep(2000); - - gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {"Testfehler"}); - - Thread.sleep(2000); - - gui.showErrorDialog("error.unknown", null); +// Thread.sleep(2000); +// +// gui.showWaitDialog(null); +// +// Thread.sleep(1000); +// +// gui.showWaitDialog("test"); +// +// Thread.sleep(1000); +// +// +// gui.showInsertCardDialog(cancelListener, "cancel"); +// +// Thread.sleep(2000); +// +// gui.showCardNotSupportedDialog(cancelListener, "cancel"); +// +// Thread.sleep(2000); +// +// PINSpec cardPinSpec = new PINSpec(4, 4, "[0-9]", "Karten-PIN"); +// +// gui.showCardPINDialog(cardPinSpec, okListener, "ok", cancelListener, "cancel"); +// +// Thread.sleep(2000); +// +// gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); +// +// Thread.sleep(4000); +// +// gui.showSignaturePINRetryDialog(signPinSpec, 2, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); +// +// Thread.sleep(2000); +// +// gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {"Testfehler"}, null, null); +// +// Thread.sleep(2000); +// +// gui.showErrorDialog("error.test", new Object[] {"Testfehler", "noch ein TestFehler"}); +// +// Thread.sleep(2000); +// +// gui.showErrorDialog("error.no.hashdata", null); +// +// Thread.sleep(2000); +// +// gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {"Testfehler"}); +// +// Thread.sleep(2000); +// +// gui.showErrorDialog("error.unknown", null); // gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save"); // gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save"); // Thread.sleep(2000); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } +// } catch (InterruptedException ex) { +// ex.printStackTrace(); +// } } } diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java index fb8f2432..eaa4d6ad 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java @@ -37,10 +37,10 @@ public class BKUGuiProxy implements BKUGUIFacade { return delegate.getPin(); } - @Override - public void init(Container contentPane, Locale locale, URL bgImage, ActionListener helpListener) { - delegate.init(contentPane, locale, bgImage, helpListener); - } +// @Override +// public void init(Container contentPane, Locale locale, URL bgImage, ActionListener helpListener) { +// delegate.init(contentPane, locale, bgImage, helpListener); +// } @Override public Locale getLocale() { @@ -126,11 +126,9 @@ public class BKUGuiProxy implements BKUGUIFacade { @Override public void showHashDataInputDialog(List signedReferences, - boolean externalDisplay, ActionListener okListener, String okCommand) { showDialog(); - delegate.showHashDataInputDialog(signedReferences, externalDisplay, okListener, - okCommand); + delegate.showHashDataInputDialog(signedReferences, okListener, okCommand); } } diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java index 19e6a657..bfce0f0d 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java @@ -109,7 +109,7 @@ public class LocalSignRequestHandler extends SignRequestHandler { log.error("dsig:SignedInfo does not contain a data reference"); throw new Exception("dsig:SignedInfo does not contain a data reference"); } - gui.showHashDataInputDialog(selectedHashDataInputs, false, this, "ok"); + gui.showHashDataInputDialog(selectedHashDataInputs, this, "ok"); } private ByteArrayHashDataInput getByteArrayHashDataInput(HashDataInput hashDataInput) throws IOException { diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTALFactory.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTALFactory.java index cad8cfb6..7012fec0 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTALFactory.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/SMCCSTALFactory.java @@ -48,7 +48,6 @@ public class SMCCSTALFactory implements STALFactory { if (locale != null) { dialog.setLocale(locale); } - BKUGUIFacade gui = BKUGUIFactory.createGUI(BKUGUIFactory.ADVANCED_GUI); DefaultHelpListener helpListener = null; try { if (helpURL != null) { @@ -60,7 +59,11 @@ public class SMCCSTALFactory implements STALFactory { } catch (MalformedURLException ex) { log.error("failed to configure help listener: " + ex.getMessage(), ex); } - gui.init(dialog.getContentPane(), dialog.getLocale(), null, helpListener); + BKUGUIFacade gui = BKUGUIFactory.createGUI(dialog.getContentPane(), + dialog.getLocale(), + BKUGUIFactory.ADVANCED_GUI, + null, + helpListener); stal = new SMCCSTAL(new BKUGuiProxy(dialog, gui), dialog); dialog.setPreferredSize(new Dimension(400, 200)); dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); diff --git a/BKUOnline/src/main/webapp/HTTP-ohne.html b/BKUOnline/src/main/webapp/HTTP-ohne.html index 112a1d92..607fa5d4 100644 --- a/BKUOnline/src/main/webapp/HTTP-ohne.html +++ b/BKUOnline/src/main/webapp/HTTP-ohne.html @@ -101,7 +101,7 @@ legend { Frame Browser - Applet +

diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java index 9d23315c..38247174 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -38,6 +38,8 @@ import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.CellRendererPane; import javax.swing.GroupLayout; import javax.swing.ImageIcon; @@ -50,8 +52,12 @@ import javax.swing.JPasswordField; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.LayoutStyle; +import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; import javax.swing.table.TableModel; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -1013,80 +1019,75 @@ public class BKUGUIImpl implements BKUGUIFacade { } if (signedReferences.size() == 1) { - ActionListener saveHashDataListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - HashDataInput hdi = signedReferences.get(0); - showSaveHashDataInputDialog(Collections.singletonList(hdi), okListener, okCommand); - } - }; - showHashDataViewer(signedReferences.get(0), saveHashDataListener, "save"); + try { + log.debug("scheduling hashdata viewer"); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + ActionListener saveHashDataListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + HashDataInput hdi = signedReferences.get(0); + showSaveHashDataInputDialog(Collections.singletonList(hdi), okListener, okCommand); + } + }; + showHashDataViewer(signedReferences.get(0), saveHashDataListener, "save"); + } + }); + + } catch (InterruptedException ex) { + log.error("Failed to display HashDataViewer: " + ex.getMessage()); + } catch (InvocationTargetException ex) { + log.error("Failed to display HashDataViewer: " + ex.getMessage()); + } } else { - HashDataTableModel tableModel = new HashDataTableModel(signedReferences); - showSignedReferencesListDialog(tableModel, okListener, okCommand); + showSignedReferencesListDialog(signedReferences, okListener, okCommand); } } /** * Opens HashDataViewer on mouse clicked event */ - public class HashDataMouseListener extends MouseAdapter { - - private HashDataInput hashData; - - public void setHashData(HashDataInput hashData) { - this.hashData = hashData; - } - - @Override - public void mouseClicked(MouseEvent e) { - ActionListener saveListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - showSaveHashDataInputDialog(Collections.singletonList(hashData), null, null); - } - }; - showHashDataViewer(hashData, saveListener, "save"); - super.mouseClicked(e); - } - - - - } +// public class HashDataMouseListener extends MouseAdapter { +// +// private HashDataInput hashData; +// +// public void setHashData(HashDataInput hashData) { +// this.hashData = hashData; +// } +// +// @Override +// public void mouseClicked(MouseEvent e) { +// ActionListener saveListener = new ActionListener() { +// +// @Override +// public void actionPerformed(ActionEvent e) { +// showSaveHashDataInputDialog(Collections.singletonList(hashData), null, null); +// } +// }; +// showHashDataViewer(hashData, saveListener, "save"); +// super.mouseClicked(e); +// } +// } /** - * blocks until dialog returns (is closed) + * has to be called from event dispatcher thread * @param hashDataText * @param saveListener * @param saveCommand */ private void showHashDataViewer(final HashDataInput hashDataInput, final ActionListener saveListener, final String saveCommand) { - try { - log.debug("scheduling plaintext hashdatainput dialog"); - - // avoid double-clicks on hashdata link - SwingUtilities.invokeAndWait(new Runnable() { - - @Override - public void run() { - - log.debug("show plaintext hashdatainput dialog"); + log.debug("show hashdata viewer"); - ActionListener l = helpListener.getActionListener(); - HashDataViewer.showHashDataInput(contentPane, hashDataInput, messages, saveListener, saveCommand, l); - } - }); - - } catch (InterruptedException ex) { - log.error("Failed to display HashDataViewer: " + ex.getMessage()); - } catch (InvocationTargetException ex) { - log.error("Failed to display HashDataViewer: " + ex.getMessage()); - } + ActionListener l = helpListener.getActionListener(); + HashDataViewer.showHashDataInput(contentPane, hashDataInput, messages, saveListener, saveCommand, l); } - private void showSignedReferencesListDialog(final HashDataTableModel signedReferences, final ActionListener backListener, final String backCommand) { + private void showSignedReferencesListDialog(final List signedReferences, final ActionListener backListener, final String backCommand) { log.debug("scheduling signed references list dialog"); @@ -1109,21 +1110,40 @@ public class BKUGUIImpl implements BKUGUIFacade { JLabel refIdLabel = new JLabel(); refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); String refIdLabelPattern = messages.getString(MESSAGE_HASHDATALIST); - refIdLabel.setText(MessageFormat.format(refIdLabelPattern, new Object[]{signedReferences.getRowCount()})); + refIdLabel.setText(MessageFormat.format(refIdLabelPattern, new Object[]{signedReferences.size()})); - JTable hashDataTable = new JTable(signedReferences); - hashDataTable.setDefaultRenderer(HashDataInput.class, signedReferences.getRenderer()); - + HashDataTableModel tableModel = new HashDataTableModel(signedReferences); + JTable hashDataTable = new JTable(tableModel); +// hashDataTable.setDefaultRenderer(HashDataInput.class, signedReferences.getRenderer()); hashDataTable.setTableHeader(null); - // hashDataTable.setShowVerticalLines(false); - hashDataTable.setRowSelectionAllowed(true); -// TableColumn selectCol = hashDataTable.getColumnModel().getColumn(1); -// selectCol.setMinWidth(CHECKBOX_WIDTH); -// selectCol.setMaxWidth(CHECKBOX_WIDTH); + + hashDataTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + hashDataTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(final ListSelectionEvent e) { + //invoke later to allow thread to paint selection background + SwingUtilities.invokeLater(new Runnable() { -// hashDataTable.setPreferredScrollableViewportSize(mainPanel.getPreferredSize()); + @Override + public void run() { + ListSelectionModel lsm = (ListSelectionModel) e.getSource(); + int selectionIdx = lsm.getMinSelectionIndex(); + if (selectionIdx >= 0) { + final HashDataInput selection = signedReferences.get(selectionIdx); + showHashDataViewer(selection, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showSaveHashDataInputDialog(Collections.singletonList(selection), null, null); + } + }, "save"); + } + } + }); + } + }); + JScrollPane hashDataScrollPane = new JScrollPane(hashDataTable); GroupLayout mainPanelLayout = new GroupLayout(mainPanel); @@ -1174,6 +1194,12 @@ public class BKUGUIImpl implements BKUGUIFacade { }); } + /** + * + * @param signedRefs + * @param okListener may be null + * @param okCommand + */ private void showSaveHashDataInputDialog(final List signedRefs, final ActionListener okListener, final String okCommand) { log.debug("scheduling save hashdatainput dialog"); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java index a6709860..9a43e99d 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java @@ -17,21 +17,8 @@ package at.gv.egiz.bku.gui; import at.gv.egiz.stal.HashDataInput; -import java.awt.Color; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; import java.util.List; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JTable; import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableCellRenderer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -43,17 +30,15 @@ class HashDataTableModel extends DefaultTableModel { protected static final Log log = LogFactory.getLog(HashDataTableModel.class); - protected Class[] types = new Class[]{HashDataInput.class}; + protected Class[] types = new Class[]{ String.class, String.class }; protected List hashDataInputs; - private HashDataLinkRenderer renderer; public HashDataTableModel(List hashDataInputs) { - super(0, 1); + super(0, 2); this.hashDataInputs = hashDataInputs; for (HashDataInput hdi : hashDataInputs) { - addRow(new Object[]{hdi}); + addRow(new Object[]{hdi.getReferenceId(), hdi.getMimeType()}); } - this.renderer = new HashDataLinkRenderer(); } @Override @@ -66,46 +51,45 @@ class HashDataTableModel extends DefaultTableModel { return false; } - - - public HashDataLinkRenderer getRenderer() { - return renderer; - } +// public HashDataInput getValue(int rowIndex) { +// return hashDataInputs.get(rowIndex); +// } +// - public class HashDataLinkRenderer extends JLabel - implements TableCellRenderer { -// extends DefaultTableCellRenderer { - -// protected ActionListener saveHashDataListener; +// public class HashDataLinkRenderer extends JLabel +// implements TableCellRenderer { +//// extends DefaultTableCellRenderer { +// +//// protected ActionListener saveHashDataListener; +//// +//// public HashDataLinkRenderer(ActionListener saveHashDataListener) { +//// this.saveHashDataListener = saveHashDataListener; +//// } +// +// @Override +// public Component getTableCellRendererComponent(JTable table, +// Object value, +// boolean isSelected, +// boolean hasFocus, +// final int row, +// int column) { +// final HashDataInput hdi = (HashDataInput) value; +// log.debug("render hashdatainput " + hdi.getReferenceId() + " - (" + row + "," + column + ") " + isSelected + hasFocus); +// setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); +// setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD)); +// setText(hdi.getReferenceId() + " (" + hdi.getMimeType() + ")"); +// addMouseListener(new MouseAdapter() { +// +// @Override +// public void mouseClicked(MouseEvent e) { +// log.debug("received mouseclick on " + hdi.getReferenceId()); +//// saveHashDataListener.actionPerformed(); +// JOptionPane.showInputDialog(hashDataInputs.get(row).getReferenceId()); +// } +// +// }); // -// public HashDataLinkRenderer(ActionListener saveHashDataListener) { -// this.saveHashDataListener = saveHashDataListener; +// return this; // } - - @Override - public Component getTableCellRendererComponent(JTable table, - Object value, - boolean isSelected, - boolean hasFocus, - final int row, - int column) { - final HashDataInput hdi = (HashDataInput) value; - log.debug("render hashdatainput " + hdi.getReferenceId() + " - (" + row + "," + column + ") " + isSelected + hasFocus); - setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD)); - setText(hdi.getReferenceId() + " (" + hdi.getMimeType() + ")"); - addMouseListener(new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent e) { - log.debug("received mouseclick on " + hdi.getReferenceId()); -// saveHashDataListener.actionPerformed(); - JOptionPane.showInputDialog(hashDataInputs.get(row).getReferenceId()); - } - - }); - - return this; - } - } +// } } \ No newline at end of file diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java index db66bd52..263c3c04 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java @@ -16,6 +16,7 @@ */ package at.gv.egiz.bku.gui; +import at.gv.egiz.bku.gui.html.RestrictedHTMLEditorKit; import at.gv.egiz.stal.HashDataInput; import java.awt.Component; import java.awt.Container; @@ -45,6 +46,7 @@ import javax.swing.JScrollPane; import javax.swing.LayoutStyle; import javax.swing.text.Document; import javax.swing.text.EditorKit; +import javax.swing.text.StyledEditorKit; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -182,9 +184,11 @@ public class HashDataViewer extends JDialog JEditorPane viewer = new JEditorPane(); if ("text/plain".equals(mimeType)) { + //line wrapping, etc. + viewer.setEditorKit(new StyledEditorKit()); viewer.setFont(new Font(PLAINTEXT_FONT, viewer.getFont().getStyle(), viewer.getFont().getSize())); // } else if ("text/html".equals(mimeType)) { -// viewer.setEditorKitForContentType("text/html", new RestrictedHTMLEditorKit()); +// viewer.setEditorKit(new RestrictedHTMLEditorKit()); } viewer.setEditable(false); viewer.setContentType(mimeType); diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index 82b42d0f..fec097f5 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -81,7 +81,7 @@ public class BKUGUIWorker implements Runnable { }; HashDataInput signedRef1 = new ByteArrayHashDataInput( "Ich bin ein einfacher Text mit Umlauten: öäüßéç@€\n123\n456\n\tHello, world!\n\nlkjsd\nnksdjf".getBytes(), - "ref-id-000000001", + "ref-id-0000000000000000000000001", "text/plain", "UTF-8"); diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 26905f50..d041a8cb 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -48,7 +48,6 @@ import at.gv.egiz.stal.SignResponse; import at.gv.egiz.stal.signedinfo.ObjectFactory; import at.gv.egiz.stal.signedinfo.SignedInfoType; import at.gv.egiz.stal.util.JCEAlgorithmNames; -import java.awt.event.ActionListener; import java.security.DigestException; import java.util.List; @@ -128,9 +127,6 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen return true; } -// @Override -// public String providePIN(PINSpec spec, int retries) { - class STALPinProvider implements PINProvider { protected SignedInfoType signedInfo; @@ -178,7 +174,7 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen } else if (actionCommand.equals("sign")) { retryCounter++; return new String(gui.getPin()); - } else if (actionCommand.equals("ok")) { + } else if (actionCommand.equals("hashDataDone")) { showSignaturePINDialog(spec, retries); } else if (actionCommand.equals("error")) { return null; -- cgit v1.2.3 From 05fdd03fdc275a3b728b6b6b5892c9fae5e401ee Mon Sep 17 00:00:00 2001 From: wbauer Date: Fri, 28 Nov 2008 12:07:40 +0000 Subject: Changed session handling strategy when reconnecting (eg. reload pressed) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@224 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/online/webapp/BKURequestHandler.java | 8 +++++--- .../main/webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar | Bin 0 -> 182156 bytes .../java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 8 ++------ 3 files changed, 7 insertions(+), 9 deletions(-) create mode 100644 BKUOnline/src/main/webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar (limited to 'smccSTAL/src') diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java index f31559cd..3aa6bc19 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java @@ -75,9 +75,11 @@ public class BKURequestHandler extends SpringBKUServlet { HttpSession session = req.getSession(false); if (session != null) { log.warn("Already a session with id: " + session.getId() - + " active, deleting this one"); - getBindingProcessorManager().removeBindingProcessor( - IdFactory.getInstance().createId(session.getId())); + + " active, continuing"); + RequestDispatcher dispatcher = getServletContext().getNamedDispatcher(BKU_APPLET_JSP); + log.debug("forward to applet"); + dispatcher.forward(req, resp); + return; } session = req.getSession(true); if (log.isDebugEnabled()) { diff --git a/BKUOnline/src/main/webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar b/BKUOnline/src/main/webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar new file mode 100644 index 00000000..669a1f92 Binary files /dev/null and b/BKUOnline/src/main/webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar differ diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 04d8d0dd..55f51b22 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -24,8 +24,6 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,7 +34,6 @@ import at.gv.egiz.stal.InfoboxReadRequest; import at.gv.egiz.stal.STAL; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; -import java.util.Collections; public abstract class AbstractSMCCSTAL implements STAL { private static Log log = LogFactory.getLog(AbstractSMCCSTAL.class); @@ -106,7 +103,7 @@ public abstract class AbstractSMCCSTAL implements STAL { log.info("Interrupt in handleRequest, do not retry"); throw e; } catch (Exception e) { - log.info("Error while handling STAL request:" + e); + log.info("Error while handling STAL request:", e); if (++retryCounter < maxRetries) { signatureCard.disconnect(true); signatureCard = null; @@ -143,8 +140,7 @@ public abstract class AbstractSMCCSTAL implements STAL { } } catch (InterruptedException ex) { log.error("got interrupted, return ErrorResponse 6001"); - responseList = Collections.singletonList((STALResponse) new ErrorResponse(6001)); - break; + throw new RuntimeException(ex); } } -- cgit v1.2.3 From 2df9621154ad057f6cace73efe49c9ef42515fde Mon Sep 17 00:00:00 2001 From: mcentner Date: Tue, 9 Dec 2008 08:14:43 +0000 Subject: Refactored STAL interface. Additional infobox functionality. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@236 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/bku/local/stal/LocalBKUWorker.java | 4 +- .../src/main/webapp/WEB-INF/applicationContext.xml | 9 +- .../stal/service/impl/STALRequestBrokerImpl.java | 2 +- STAL/src/main/java/at/gv/egiz/stal/STAL.java | 2 +- .../gv/egiz/bku/slcommands/SLCommandFactory.java | 38 +++- .../slcommands/impl/AbstractBinaryFileInfobox.java | 4 +- .../impl/AbstractInfoboxCommandImpl.java | 9 + .../bku/slcommands/impl/AbstractInfoboxImpl.java | 19 ++ .../slcommands/impl/CardChannelInfoboxImpl.java | 235 +++++++++++++++++++++ .../at/gv/egiz/bku/slcommands/impl/Infobox.java | 21 +- .../slcommands/impl/InfoboxReadCommandImpl.java | 9 - .../bku/slcommands/impl/InfoboxReadResultImpl.java | 12 ++ .../slcommands/impl/InfoboxUpdateCommandImpl.java | 124 ++--------- .../gv/egiz/bku/slcommands/impl/SLResultImpl.java | 56 +++++ .../at/gv/egiz/bku/slcommands/impl/STALHelper.java | 2 +- .../test/java/at/gv/egiz/stal/dummy/DummySTAL.java | 2 +- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 30 ++- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 12 +- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 12 +- .../java/at/gv/egiz/smcc/SignatureCardFactory.java | 8 +- .../main/java/at/gv/egiz/smcc/util/SMCCHelper.java | 4 +- .../java/at/gv/egiz/smcc/util/SmartCardIO.java | 9 +- .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 2 +- .../java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java | 15 +- .../at/gv/egiz/bku/utils/DebugOutputStream.java | 48 +++++ .../java/at/gv/egiz/bku/utils/DebugReader.java | 58 +++++ .../java/at/gv/egiz/bku/utils/DebugWriter.java | 55 +++++ 27 files changed, 657 insertions(+), 144 deletions(-) create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CardChannelInfoboxImpl.java create mode 100644 utils/src/main/java/at/gv/egiz/bku/utils/DebugOutputStream.java create mode 100644 utils/src/main/java/at/gv/egiz/bku/utils/DebugReader.java create mode 100644 utils/src/main/java/at/gv/egiz/bku/utils/DebugWriter.java (limited to 'smccSTAL/src') diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java index 57b159ad..91d0aba0 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java @@ -22,6 +22,8 @@ import at.gv.egiz.stal.QuitRequest; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.ext.APDUScriptRequest; + import java.util.List; import javax.swing.JDialog; @@ -40,7 +42,7 @@ public class LocalBKUWorker extends AbstractBKUWorker { } @Override - public List handleRequest(List requestList) { + public List handleRequest(List requestList) { signatureCard = null; List responses = super.handleRequest(requestList); // container.setVisible(false); diff --git a/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml b/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml index 5ac12ece..eb7d5b7a 100644 --- a/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml +++ b/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml @@ -59,6 +59,9 @@ + @@ -76,9 +79,9 @@ - - - + diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java index e7fb928a..5e3a1a99 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java @@ -85,7 +85,7 @@ public class STALRequestBrokerImpl implements STALRequestBroker { * @pre requests: either single SignRequest, QuitRequest or multiple ReadInfoboxRequests */ @Override - public List handleRequest(List stalRequests) { + public List handleRequest(List stalRequests) { if (interrupted) { return null; } diff --git a/STAL/src/main/java/at/gv/egiz/stal/STAL.java b/STAL/src/main/java/at/gv/egiz/stal/STAL.java index de29de9a..7fa7cb45 100644 --- a/STAL/src/main/java/at/gv/egiz/stal/STAL.java +++ b/STAL/src/main/java/at/gv/egiz/stal/STAL.java @@ -32,7 +32,7 @@ public interface STAL { * @param aRequestList * @return */ - public List handleRequest(List aRequestList); + public List handleRequest(List aRequestList); /** * Sets the preferred locale for userinteraction (e.g. PIN dialogs). diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java index 9c98ef8a..bec2b253 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java @@ -17,6 +17,7 @@ package at.gv.egiz.bku.slcommands; import java.io.IOException; +import java.io.Reader; import java.net.URL; import java.util.HashMap; import java.util.Map; @@ -41,10 +42,12 @@ import org.apache.commons.logging.LogFactory; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; +import at.buergerkarte.namespaces.cardchannel.ObjectFactory; import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLExceptionMessages; import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.utils.DebugReader; import at.gv.egiz.slbinding.RedirectEventFilter; import at.gv.egiz.slbinding.RedirectUnmarshallerListener; @@ -163,8 +166,9 @@ public class SLCommandFactory { if (jaxbContext == null) { try { String slPkg = at.buergerkarte.namespaces.securitylayer._1.ObjectFactory.class.getPackage().getName(); - String xmldsigPkg = org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName(); - setJaxbContext(JAXBContext.newInstance(slPkg + ":" + xmldsigPkg)); + String xmldsigPkg = org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName(); + String cardChannelPkg = at.buergerkarte.namespaces.cardchannel.ObjectFactory.class.getPackage().getName(); + setJaxbContext(JAXBContext.newInstance(slPkg + ":" + xmldsigPkg + ":" + cardChannelPkg)); } catch (JAXBException e) { log.error("Failed to setup JAXBContext security layer request.", e); throw new SLRuntimeException(e); @@ -325,12 +329,31 @@ public class SLCommandFactory { */ @SuppressWarnings("unchecked") public SLCommand createSLCommand(Source source, SLCommandContext context) - throws SLCommandException, SLRuntimeException, SLRequestException { + throws SLCommandException, SLRuntimeException, SLRequestException { + + DebugReader dr = null; + if (log.isTraceEnabled() && source instanceof StreamSource) { + StreamSource streamSource = (StreamSource) source; + if (streamSource.getReader() != null) { + dr = new DebugReader(streamSource.getReader(), "SLCommand unmarshalled from:\n"); + streamSource.setReader(dr); + } + } - Object object = unmarshal(source); + Object object; + try { + object = unmarshal(source); + } catch (SLRequestException e) { + throw e; + } finally { + if (dr != null) { + log.trace(dr.getCachedString()); + } + } + if (!(object instanceof JAXBElement)) { // invalid request - log.info("Invalid security layer request. " + object.toString()); + log.info("Invalid security layer request. " + object.toString()); throw new SLRequestException(3002, SLExceptionMessages.EC3002_INVALID, new Object[]{object.toString()}); } @@ -343,7 +366,9 @@ public class SLCommandFactory { throw new SLCommandException(4011, SLExceptionMessages.EC4011_NOTIMPLEMENTED, new Object[]{qName.toString()}); } - + + + // try to instantiate SLCommand slCommand; try { @@ -360,6 +385,7 @@ public class SLCommandFactory { e); throw new SLRuntimeException(e); } + slCommand.init(context, (JAXBElement) object); return slCommand; diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java index 07ca639c..23394bd5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java @@ -37,7 +37,7 @@ public abstract class AbstractBinaryFileInfobox extends AbstractInfoboxImpl impl /** * Is this infobox' content an XML entity? */ - private boolean isXMLEntity = false; + protected boolean isXMLEntity = false; /** * @return true if this infobox' content is an XML entity or false otherwise. @@ -61,8 +61,6 @@ public abstract class AbstractBinaryFileInfobox extends AbstractInfoboxImpl impl } } - - } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java index 305769a8..8a7edb71 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java @@ -52,4 +52,13 @@ public abstract class AbstractInfoboxCommandImpl extends SLCommandImpl { */ protected abstract String getInfoboxIdentifier(T request); + + public String getInfoboxIdentifier() { + if (infobox != null) { + return infobox.getIdentifier(); + } else { + return null; + } + } + } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java index e5c7afcc..564cb8ff 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java @@ -16,6 +16,13 @@ */ package at.gv.egiz.bku.slcommands.impl; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxUpdateRequestType; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.InfoboxUpdateResult; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; + /** * An abstract base class for {@link Infobox} implementations. * @@ -23,4 +30,16 @@ package at.gv.egiz.bku.slcommands.impl; */ public abstract class AbstractInfoboxImpl implements Infobox { + @Override + public InfoboxReadResult read(InfoboxReadRequestType request, + SLCommandContext cmdCtx) throws SLCommandException { + throw new SLCommandException(4011); + } + + @Override + public InfoboxUpdateResult update(InfoboxUpdateRequestType request, + SLCommandContext cmdCtx) throws SLCommandException { + throw new SLCommandException(4011); + } + } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CardChannelInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CardChannelInfoboxImpl.java new file mode 100644 index 00000000..4b1cc779 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CardChannelInfoboxImpl.java @@ -0,0 +1,235 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.slcommands.impl; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.WeakHashMap; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.buergerkarte.namespaces.cardchannel.ATRType; +import at.buergerkarte.namespaces.cardchannel.CommandAPDUType; +import at.buergerkarte.namespaces.cardchannel.ObjectFactory; +import at.buergerkarte.namespaces.cardchannel.ResetType; +import at.buergerkarte.namespaces.cardchannel.ResponseAPDUType; +import at.buergerkarte.namespaces.cardchannel.ResponseType; +import at.buergerkarte.namespaces.cardchannel.ScriptType; +import at.buergerkarte.namespaces.cardchannel.VerifyAPDUType; +import at.buergerkarte.namespaces.securitylayer._1.Base64XMLContentType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxUpdateRequestType; +import at.buergerkarte.namespaces.securitylayer._1.XMLContentType; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.InfoboxUpdateResult; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.ext.APDUScriptRequest; +import at.gv.egiz.stal.ext.APDUScriptResponse; +import at.gv.egiz.stal.ext.APDUScriptRequest.RequestScriptElement; +import at.gv.egiz.stal.ext.APDUScriptResponse.ResponseScriptElement; + +public class CardChannelInfoboxImpl extends AbstractBinaryFileInfobox { + + private static Log log = LogFactory.getLog(CardChannelInfoboxImpl.class); + + private static WeakHashMap> scriptResults = new WeakHashMap>(); + + private static JAXBContext jaxbContext; + + static { + try { + jaxbContext = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName()); + } catch (JAXBException e) { + throw new SLRuntimeException("Failed to initalize CardChannel infobox.", e); + } + } + + public CardChannelInfoboxImpl() { + isXMLEntity = true; + } + + @Override + public String getIdentifier() { + return "CardChannel"; + } + + @Override + public InfoboxReadResult read(InfoboxReadRequestType request, + SLCommandContext cmdCtx) throws SLCommandException { + + at.buergerkarte.namespaces.securitylayer._1.ObjectFactory objectFactory + = new at.buergerkarte.namespaces.securitylayer._1.ObjectFactory(); + + Base64XMLContentType content = objectFactory.createBase64XMLContentType(); + XMLContentType xmlContent = objectFactory.createXMLContentType(); + content.setXMLContent(xmlContent); + + JAXBElement response = scriptResults.get(cmdCtx.getSTAL()); + if (response != null) { + xmlContent.getContent().add(response); + } + + return new InfoboxReadResultImpl(content); + + } + + @SuppressWarnings("unchecked") + @Override + public InfoboxUpdateResult update(InfoboxUpdateRequestType request, + SLCommandContext cmdCtx) throws SLCommandException { + + Base64XMLContentType binaryFileParameters = request.getBinaryFileParameters(); + + if (binaryFileParameters.getBase64Content() != null) { + log.info("Got Base64Content but ContentIsXMLEntity is true."); + throw new SLCommandException(4010); + } + + XMLContentType content = binaryFileParameters.getXMLContent(); + if (content instanceof at.gv.egiz.slbinding.impl.XMLContentType) { + + ByteArrayOutputStream redirectedStream = ((at.gv.egiz.slbinding.impl.XMLContentType) content).getRedirectedStream(); + if (redirectedStream != null) { + + if (log.isDebugEnabled()) { + + StringBuilder sb = new StringBuilder(); + sb.append("CardChannel script:\n"); + try { + sb.append(new String(redirectedStream.toByteArray(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + sb.append(e.getMessage()); + } + log.debug(sb.toString()); + } + + Object object; + try { + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + object = unmarshaller.unmarshal(new ByteArrayInputStream(redirectedStream.toByteArray())); + } catch (JAXBException e) { + log.info("Failed to parse CardChannel script.", e); + throw new SLCommandException(4011); + } + + if (object instanceof JAXBElement) { + executeCardChannelScript(((JAXBElement) object).getValue(), cmdCtx); + return new InfoboxUpdateResultImpl(); + } + + } + + + } + log.info("Infobox identifier is '" + getIdentifier() + "' but XMLContent does not contain 'Script'."); + throw new SLCommandException(4010); + + } + + protected void executeCardChannelScript(ScriptType script, + SLCommandContext cmdCtx) throws SLCommandException { + + List resetOrCommandAPDUOrVerifyAPDU = script.getResetOrCommandAPDUOrVerifyAPDU(); + List requestScript = new ArrayList(); + + for (Object element : resetOrCommandAPDUOrVerifyAPDU) { + + if (element instanceof ResetType) { + + requestScript.add(new APDUScriptRequest.Reset()); + + } else if (element instanceof CommandAPDUType) { + + CommandAPDUType commandAPDU = (CommandAPDUType) element; + int sequence = (commandAPDU.getSequence() != null) + ? commandAPDU.getSequence().intValue() + : 0; + + requestScript.add( + new APDUScriptRequest.Command( + sequence, + commandAPDU.getValue(), + commandAPDU.getExpectedSW())); + + } else if (element instanceof VerifyAPDUType) { + log.warn("CardChannel script command 'VerifyAPDU' not implemented."); + throw new SLCommandException(4011); + } + } + + APDUScriptRequest scriptRequest = new APDUScriptRequest(requestScript); + + STAL stal = cmdCtx.getSTAL(); + STALHelper helper = new STALHelper(stal); + + helper.transmitSTALRequest(Collections.singletonList(scriptRequest)); + + List responseScript = ((APDUScriptResponse) helper + .nextResponse(APDUScriptResponse.class)).getScript(); + + ObjectFactory objectFactory = new ObjectFactory(); + + ResponseType responseType = objectFactory.createResponseType(); + + + for (ResponseScriptElement element : responseScript) { + + if (element instanceof APDUScriptResponse.ATR) { + + byte[] atr = ((APDUScriptResponse.ATR) element).getAtr(); + + ATRType atrType = objectFactory.createATRType(); + atrType.setValue(atr); + atrType.setRc(BigInteger.ZERO); + responseType.getATROrResponseAPDU().add(atrType); + + } else if (element instanceof APDUScriptResponse.Response) { + + APDUScriptResponse.Response response = (APDUScriptResponse.Response) element; + + ResponseAPDUType responseAPDUType = objectFactory.createResponseAPDUType(); + responseAPDUType.setSequence(BigInteger.valueOf(response.getSequence())); +// if (response.getRc() != 0) { + responseAPDUType.setRc(BigInteger.valueOf(response.getRc())); +// } + responseAPDUType.setSw(response.getSw()); + responseAPDUType.setValue(response.getApdu()); + + responseType.getATROrResponseAPDU().add(responseAPDUType); + } + + } + + scriptResults.put(stal, objectFactory.createResponse(responseType)); + } + + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java index a6f8cbb2..99d62721 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java @@ -17,7 +17,9 @@ package at.gv.egiz.bku.slcommands.impl; import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxUpdateRequestType; import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.InfoboxUpdateResult; import at.gv.egiz.bku.slcommands.SLCommandContext; import at.gv.egiz.bku.slexceptions.SLCommandException; @@ -44,10 +46,25 @@ public interface Infobox { * * @return the data read from this infobox as InfoboxReadResult * - * @throws SLCommandException - * if reading from this infobox fails + * @throws SLCommandException + * + * if reading from this infobox fails */ public InfoboxReadResult read(InfoboxReadRequestType request, SLCommandContext cmdCtx) throws SLCommandException; + /** + * Update data in this infobox. + * + * @param request + * the InfoboxUpdateRequest + * @param cmdCtx + * the command context + * @return a corresponding InfoboxUpdateResult + * @throws SLCommandException + * if updating this infobox fails + */ + public InfoboxUpdateResult update(InfoboxUpdateRequestType request, + SLCommandContext cmdCtx) throws SLCommandException; + } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java index aaa786a6..693f444f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java @@ -83,7 +83,6 @@ public class InfoboxReadCommandImpl extends AbstractInfoboxCommandImpl implements InfoboxUpdateCommand { + AbstractInfoboxCommandImpl implements InfoboxUpdateCommand { private static Log log = LogFactory.getLog(InfoboxUpdateCommandImpl.class); - public static final String INFOBOX_IDENTIFIER_CARD_CHANNEL = "CardChannel"; + @Override + public String getName() { + return "InfoboxUpdateRequest"; + } - protected String infoboxIdentifier; - - protected List cardChannelScript; - @Override - public String getInfoboxIdentifier() { - return infoboxIdentifier; + protected String getInfoboxIdentifier(InfoboxUpdateRequestType request) { + return request.getInfoboxIdentifier(); } - + @Override - public void init(SLCommandContext ctx, Object request) - throws SLCommandException { + public void init(SLCommandContext ctx, Object request) throws SLCommandException { super.init(ctx, request); InfoboxUpdateRequestType req = getRequestValue(); - infoboxIdentifier = req.getInfoboxIdentifier(); + if (req.getAssocArrayParameters() != null && + !(infobox instanceof AssocArrayInfobox)) { + log.info("Got AssocArrayParameters but Infobox type is not AssocArray."); + throw new SLCommandException(4010); + } - if (INFOBOX_IDENTIFIER_CARD_CHANNEL.equals(infoboxIdentifier)) { - - if (req.getAssocArrayParameters() != null) { - log.info("Got AssocArrayParameters but Infobox type is BinaryFile."); - throw new SLCommandException(4010); - } - - Base64XMLContentType binaryFileParameters = req.getBinaryFileParameters(); - if (binaryFileParameters == null) { - log.info("Got no BinaryFileParameters but Infobox type is BinaryFile."); - throw new SLCommandException(4010); - } - - if (binaryFileParameters.getBase64Content() == null) { - log.info("Got Base64Content but ContentIsXMLEntity is true."); - throw new SLCommandException(4010); - } - - List content = binaryFileParameters.getXMLContent().getContent(); - if (content.isEmpty()) { - log.info("Got no XMLContent but ContentIsXMLEntity is true."); - throw new SLCommandException(4010); - } - - for (Object element : content) { - if (!(element instanceof ScriptType)) { - log.info("Infobox identifier is '" + infoboxIdentifier + "' but XMLContent does not contain 'Script'."); - throw new SLCommandException(4010); - } - - setCardChannelScript(((ScriptType) element).getResetOrCommandAPDUOrVerifyAPDU()); - } - - if (getCardChannelScript() == null) { - log.info("Infobox identifier is '" + infoboxIdentifier + "' but XMLContent does not contain 'Script'."); - throw new SLCommandException(4010); - } - - } else { - throw new SLCommandException(4002, - SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, - new Object[] { infoboxIdentifier }); + if (req.getBinaryFileParameters() != null && + !(infobox instanceof BinaryFileInfobox)) { + log.info("Got BinaryFileParameters but Infobox type is not BinaryFile."); + throw new SLCommandException(4010); } } - public List getCardChannelScript() { - return cardChannelScript; - } - - public void setCardChannelScript(List cardChannelScript) { - this.cardChannelScript = cardChannelScript; - } - @Override public SLResult execute() { try { - if (INFOBOX_IDENTIFIER_CARD_CHANNEL.equals(getInfoboxIdentifier())) { - - executeCardChannelScript(); - return new InfoboxUpdateResultImpl(); - - } else { - throw new SLCommandException(4002, - SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, - new Object[] { infoboxIdentifier }); - } + return infobox.update(getRequestValue(), getCmdCtx()); } catch (SLCommandException e) { - return new ErrorResultImpl(e, cmdCtx.getLocale()); + return new ErrorResultImpl(e, getCmdCtx().getLocale()); } } - - protected void executeCardChannelScript() throws SLCommandException { - - if (cardChannelScript != null) { - - for (Object element : cardChannelScript) { - if (element instanceof ResetType) { - - } else if (element instanceof CommandAPDUType) { - - } else if (element instanceof VerifyAPDUType) { - - } - } - - } - - } - - @Override - public String getName() { - return "InfoboxUpdateRequest"; - } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java index 80bbdca8..99a3b119 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java @@ -16,6 +16,7 @@ */ package at.gv.egiz.bku.slcommands.impl; +import java.io.UnsupportedEncodingException; import java.util.Locale; import javax.xml.bind.JAXBContext; @@ -32,6 +33,7 @@ import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -45,6 +47,8 @@ import at.gv.egiz.bku.slexceptions.SLBindingException; import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLException; import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.utils.DebugOutputStream; +import at.gv.egiz.bku.utils.DebugWriter; /** * This class serves as an abstract base class for the implementation of a @@ -128,6 +132,20 @@ public abstract class SLResultImpl implements SLResult { * @param templates */ protected void writeTo(JAXBElement response, Result result, Templates templates) { + + DebugWriter dw = null; + DebugOutputStream ds = null; + if (log.isTraceEnabled() && result instanceof StreamResult) { + StreamResult streamResult = (StreamResult) result; + if (streamResult.getOutputStream() != null) { + ds = new DebugOutputStream(streamResult.getOutputStream()); + streamResult.setOutputStream(ds); + } + if (streamResult.getWriter() != null) { + dw = new DebugWriter(streamResult.getWriter()); + streamResult.setWriter(dw); + } + } TransformerHandler transformerHandler = null; if (templates != null) { @@ -151,10 +169,36 @@ public abstract class SLResultImpl implements SLResult { writeErrorTo(commandException, result, templates); } + if (ds != null) { + try { + log.trace("Marshalled result:\n" + new String(ds.getBufferedBytes(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + log.trace(e.getMessage()); + } + } + + if (dw != null) { + log.trace("Marshalled result:\n" + dw.getBufferedString()); + } + } protected void writeTo(Node node, Result result, Templates templates) { + DebugWriter dw = null; + DebugOutputStream ds = null; + if (log.isTraceEnabled() && result instanceof StreamResult) { + StreamResult streamResult = (StreamResult) result; + if (streamResult.getOutputStream() != null) { + ds = new DebugOutputStream(streamResult.getOutputStream()); + streamResult.setOutputStream(ds); + } + if (streamResult.getWriter() != null) { + dw = new DebugWriter(streamResult.getWriter()); + streamResult.setWriter(dw); + } + } + if (templates == null) { try { TransformerFactory transformerFactory = TransformerFactory.newInstance(); @@ -179,7 +223,19 @@ public abstract class SLResultImpl implements SLResult { writeErrorTo(new SLException(2008), result, templates); } } + + if (ds != null) { + try { + log.trace("Marshalled result:\n" + new String(ds.getBufferedBytes(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + log.trace(e.getMessage()); + } + } + if (dw != null) { + log.trace("Marshalled result:\n" + dw.getBufferedString()); + } + } protected void writeErrorTo(SLException slException, Result result, Templates templates) { diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java index 969288c1..0c7ce3f5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java @@ -85,7 +85,7 @@ public class STALHelper { * @param stalRequests * @throws SLCommandException */ - public void transmitSTALRequest(List stalRequests) throws SLCommandException { + public void transmitSTALRequest(List stalRequests) throws SLCommandException { List responses = stal.handleRequest(stalRequests); if (responses == null) { Log log = LogFactory.getLog(this.getClass()); diff --git a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java index 2ea0bae0..dd8b8c8f 100644 --- a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java +++ b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java @@ -71,7 +71,7 @@ public class DummySTAL implements STAL { } @Override - public List handleRequest(List requestList) { + public List handleRequest(List requestList) { List responses = new ArrayList(); for (STALRequest request : requestList) { diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java index b828e8cd..e34c4899 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -36,6 +36,7 @@ import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; @@ -53,7 +54,12 @@ public abstract class AbstractSignatureCard implements SignatureCard { int ifs_ = 254; - Card card_; + private Card card_; + + /** + * The card terminal that connects the {@link #card_}. + */ + private CardTerminal cardTerminal; protected AbstractSignatureCard(String resourceBundleName) { this.resourceBundleName = resourceBundleName; @@ -331,8 +337,9 @@ public abstract class AbstractSignatureCard implements SignatureCard { } - public void init(Card card) { + public void init(Card card, CardTerminal cardTerminal) { card_ = card; + this.cardTerminal = cardTerminal; ATR atr = card.getATR(); byte[] atrBytes = atr.getBytes(); if (atrBytes.length >= 6) { @@ -340,6 +347,11 @@ public abstract class AbstractSignatureCard implements SignatureCard { log.trace("Setting IFS (information field size) to " + ifs_); } } + + @Override + public Card getCard() { + return card_; + } protected CardChannel getCardChannel() { return card_.getBasicChannel(); @@ -372,4 +384,18 @@ public abstract class AbstractSignatureCard implements SignatureCard { } } + @Override + public void reset() throws SignatureCardException { + try { + log.debug("Disconnect and reset smart card."); + card_.disconnect(true); + log.debug("Reconnect smart card."); + if (cardTerminal != null) { + card_ = cardTerminal.connect("*"); + } + } catch (CardException e) { + throw new SignatureCardException("Failed to reset card.", e); + } + } + } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java index 42943541..439be034 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -40,6 +40,7 @@ import java.util.Enumeration; import java.util.Locale; import javax.smartcardio.Card; +import javax.smartcardio.CardTerminal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -102,7 +103,12 @@ public class SWCard implements SignatureCard { SWCard.swCardDir = swCardDir; } - public void init(Card card) { + public void init(Card card, CardTerminal cardTerminal) { + } + + @Override + public Card getCard() { + return null; } private String getFileName(String fileName) { @@ -379,4 +385,8 @@ public class SWCard implements SignatureCard { public void disconnect(boolean reset) { } + @Override + public void reset() throws SignatureCardException { + } + } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index b6a453df..d7e76dd8 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -31,6 +31,7 @@ package at.gv.egiz.smcc; import java.util.Locale; import javax.smartcardio.Card; +import javax.smartcardio.CardTerminal; public interface SignatureCard { @@ -75,12 +76,21 @@ public interface SignatureCard { } - public void init(Card card); + public void init(Card card, CardTerminal cardTerminal); + + public Card getCard(); public byte[] getCertificate(KeyboxName keyboxName) throws SignatureCardException, InterruptedException; public void disconnect(boolean reset); + + /** + * Performs a reset of the card. + * + * @throws SignatureCardException if reset fails. + */ + public void reset() throws SignatureCardException; /** * diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java index 777299d9..ab66e9a1 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java @@ -34,6 +34,7 @@ import java.util.List; import javax.smartcardio.ATR; import javax.smartcardio.Card; +import javax.smartcardio.CardTerminal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -204,6 +205,7 @@ public class SignatureCardFactory { * @param card * the smart card, or null if a software card should be * created + * @param cardTerminal TODO * * @return a SignatureCard instance * @@ -211,12 +213,12 @@ public class SignatureCardFactory { * if no implementation of the given card could be * found */ - public SignatureCard createSignatureCard(Card card) + public SignatureCard createSignatureCard(Card card, CardTerminal cardTerminal) throws CardNotSupportedException { if(card == null) { SignatureCard sCard = new SWCard(); - sCard.init(card); + sCard.init(card, cardTerminal); return sCard; } @@ -231,7 +233,7 @@ public class SignatureCardFactory { try { Class scClass = cl.loadClass(supportedCard.getImplementationClassName()); sc = (SignatureCard) scClass.newInstance(); - sc.init(card); + sc.init(card, cardTerminal); return sc; } catch (ClassNotFoundException e) { diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java index 4dae7975..f7d3bab7 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java @@ -57,7 +57,7 @@ public class SMCCHelper { SignatureCardFactory factory = SignatureCardFactory.getInstance(); if (useSWCard) { try { - signatureCard = factory.createSignatureCard(null); + signatureCard = factory.createSignatureCard(null, null); resultCode = CARD_FOUND; } catch (CardNotSupportedException e) { resultCode = CARD_NOT_SUPPORTED; @@ -83,7 +83,7 @@ public class SMCCHelper { if (c == null) { throw new CardNotSupportedException(); } - signatureCard = factory.createSignatureCard(c); + signatureCard = factory.createSignatureCard(c, cardTerminal); ATR atr = newCards.get(cardTerminal).getATR(); log.trace("Found supported card (" + signatureCard.toString() + ") " + "in terminal '" + cardTerminal.getName() + "', ATR = " diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/SmartCardIO.java b/smcc/src/main/java/at/gv/egiz/smcc/util/SmartCardIO.java index b70b44a7..b1866894 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/util/SmartCardIO.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/util/SmartCardIO.java @@ -16,6 +16,7 @@ */ package at.gv.egiz.smcc.util; +import java.security.NoSuchAlgorithmException; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -54,7 +55,13 @@ public class SmartCardIO { CardTerminals cardTerminals_; private void updateTerminalFactory() { - TerminalFactory terminalFactory = TerminalFactory.getDefault(); + TerminalFactory terminalFactory; + try { + terminalFactory = TerminalFactory.getInstance("PC/SC", null); + } catch (NoSuchAlgorithmException e) { + log.info("Failed to get TerminalFactory of type 'PC/SC'.", e); + terminalFactory = TerminalFactory.getDefault(); + } log.debug("TerminalFactory : " + terminalFactory); if ("PC/SC".equals(terminalFactory.getType())) { terminalFactory_ = terminalFactory; diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 55f51b22..6f08a135 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -121,7 +121,7 @@ public abstract class AbstractSMCCSTAL implements STAL { } @Override - public List handleRequest(List requestList) { + public List handleRequest(List requestList) { log.debug("Got request list containing " + requestList.size() + " STAL requests"); List responseList = new ArrayList(requestList diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java index 59ea141c..77997217 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Locale; import javax.smartcardio.Card; +import javax.smartcardio.CardTerminal; import org.junit.Assert; import org.junit.Before; @@ -61,7 +62,7 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements } @Override - public void init(Card card) { + public void init(Card card, CardTerminal cardTerminal) { // TODO Auto-generated method stub } @@ -71,6 +72,18 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements // TODO Auto-generated method stub } + + @Override + public Card getCard() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void reset() throws SignatureCardException { + // TODO Auto-generated method stub + + } }; return false; diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/DebugOutputStream.java b/utils/src/main/java/at/gv/egiz/bku/utils/DebugOutputStream.java new file mode 100644 index 00000000..8516b76c --- /dev/null +++ b/utils/src/main/java/at/gv/egiz/bku/utils/DebugOutputStream.java @@ -0,0 +1,48 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.utils; + +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class DebugOutputStream extends FilterOutputStream { + + private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + public DebugOutputStream(OutputStream out) { + super(out); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + buffer.write(b, off, len); + super.write(b, off, len); + } + + @Override + public void write(int b) throws IOException { + buffer.write(b); + super.write(b); + } + + public byte[] getBufferedBytes() { + return buffer.toByteArray(); + } + +} diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/DebugReader.java b/utils/src/main/java/at/gv/egiz/bku/utils/DebugReader.java new file mode 100644 index 00000000..cafe4a72 --- /dev/null +++ b/utils/src/main/java/at/gv/egiz/bku/utils/DebugReader.java @@ -0,0 +1,58 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.utils; + +import java.io.FilterReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringWriter; + +public class DebugReader extends FilterReader { + + private StringWriter buffer = new StringWriter(); + + public DebugReader(Reader in) { + super(in); + } + + public DebugReader(Reader in, String start) { + super(in); + buffer.write(start); + } + + @Override + public int read() throws IOException { + int c = super.read(); + if (c != -1) + buffer.write(c); + return c; + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + int l = super.read(cbuf, off, len); + if (l != -1 ) { + buffer.write(cbuf, off, l); + } + return l; + } + + public String getCachedString() { + return buffer.toString(); + } + +} diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/DebugWriter.java b/utils/src/main/java/at/gv/egiz/bku/utils/DebugWriter.java new file mode 100644 index 00000000..5566f927 --- /dev/null +++ b/utils/src/main/java/at/gv/egiz/bku/utils/DebugWriter.java @@ -0,0 +1,55 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.utils; + +import java.io.FilterWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; + +public class DebugWriter extends FilterWriter { + + private Writer buffer = new StringWriter(); + + public DebugWriter(Writer out) { + super(out); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + buffer.write(cbuf, off, len); + super.write(cbuf, off, len); + } + + @Override + public void write(String str, int off, int len) throws IOException { + buffer.write(str, off, len); + super.write(str, off, len); + } + + @Override + public void write(int c) throws IOException { + buffer.write(c); + super.write(c); + } + + public String getBufferedString() { + return buffer.toString(); + } + + +} -- cgit v1.2.3 From 887f6727479f3ae3d89a08ba619f9382b450e4c1 Mon Sep 17 00:00:00 2001 From: mcentner Date: Fri, 12 Dec 2008 11:48:47 +0000 Subject: Updated SMCC to support non-blocking PIN entry. Added SV-Personendaten infobox implementation. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@248 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/webapp/WEB-INF/applicationContext.xml | 3 + .../gv/egiz/bku/binding/DataUrlConnectionImpl.java | 1 + .../bku/binding/LegacyDataUrlConnectionImpl.java | 3 + .../slcommands/impl/AbstractAssocArrayInfobox.java | 96 +++-- .../impl/SVPersonendatenInfoboxImpl.java | 323 +++++++++++++++++ .../impl/SVPersonendatenInfoboxImplTest.java | 147 ++++++++ smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 320 +++++++++-------- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 214 +++++++----- .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 386 +++++++++++++-------- .../smcc/SecurityStatusNotSatisfiedException.java | 38 ++ .../gv/egiz/smcc/VerificationFailedException.java | 65 ++++ .../test/java/at/gv/egiz/smcc/STARCOSCardTest.java | 40 ++- .../bku/smccstal/InfoBoxReadRequestHandler.java | 3 + 13 files changed, 1219 insertions(+), 420 deletions(-) create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImpl.java create mode 100644 bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/SecurityStatusNotSatisfiedException.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/VerificationFailedException.java (limited to 'smccSTAL/src') diff --git a/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml b/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml index eb7d5b7a..2ddd46a1 100644 --- a/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml +++ b/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml @@ -82,6 +82,9 @@ + diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java index 408330cc..57d89c89 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java @@ -100,6 +100,7 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI { } if (hostnameVerifier != null) { log.debug("Setting custom hostname verifier"); + https.setHostnameVerifier(hostnameVerifier); } } else { log.trace("No secure connection with: "+url+ " class="+connection.getClass()); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java index ef8034aa..452c45e5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java @@ -80,6 +80,7 @@ public class LegacyDataUrlConnectionImpl implements DataUrlConnectionSPI { } if (hostnameVerifier != null) { log.debug("Setting custom hostname verifier"); + https.setHostnameVerifier(hostnameVerifier); } } connection.setDoOutput(true); @@ -229,6 +230,8 @@ public class LegacyDataUrlConnectionImpl implements DataUrlConnectionSPI { public DataUrlConnectionSPI newInstance() { DataUrlConnectionSPI uc = new LegacyDataUrlConnectionImpl(); uc.setConfiguration(config); + uc.setSSLSocketFactory(sslSocketFactory); + uc.setHostnameVerifier(hostnameVerifier); return uc; } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java index e49ed6c0..e7f96c06 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java @@ -16,12 +16,17 @@ */ package at.gv.egiz.bku.slcommands.impl; +import java.io.ByteArrayOutputStream; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.regex.Pattern; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,6 +41,7 @@ import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayTy import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadValue; import at.gv.egiz.bku.slcommands.InfoboxReadResult; import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLCommandFactory; import at.gv.egiz.bku.slexceptions.SLCommandException; /** @@ -54,7 +60,7 @@ public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl /** * The search string pattern. */ - public static final String SEARCH_STRING_PATTERN = ".&&[^/](/.&&[^/])*"; + public static final String SEARCH_STRING_PATTERN = "(.&&[^/])+(/.&&[^/])*"; /** * @return the keys available in this infobox. @@ -93,6 +99,11 @@ public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl return Arrays.asList(getKeys()); } + if (!searchString.contains("*")) { + Arrays.asList(getKeys()).contains(searchString); + return Collections.singletonList(searchString); + } + if (Pattern.matches(SEARCH_STRING_PATTERN, searchString)) { // for (int i = 0; i < searchString.length(); i++) { @@ -160,15 +171,10 @@ public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl protected InfoboxReadResult readPairs(ReadPairs readPairs, SLCommandContext cmdCtx) throws SLCommandException { if (readPairs.isValuesAreXMLEntities() && !isValuesAreXMLEntities()) { - log.info("Got valuesAreXMLEntities=" + readPairs + " but infobox type is binary."); + log.info("Got valuesAreXMLEntities=" + readPairs.isValuesAreXMLEntities() + " but infobox type is binary."); throw new SLCommandException(4010); } - if (!readPairs.isValuesAreXMLEntities() && isValuesAreXMLEntities()) { - log.info("Got valuesAreXMLEntities=" + readPairs + " but infobox type is XML."); - throw new SLCommandException(4010); - } - List selectedKeys = selectKeys(readPairs.getSearchString()); if (readPairs.isUserMakesUnique() && selectedKeys.size() > 1) { @@ -177,26 +183,10 @@ public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl throw new SLCommandException(4010); } - ObjectFactory objectFactory = new ObjectFactory(); - - InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory.createInfoboxReadDataAssocArrayType(); - - Map values = getValues(selectedKeys, cmdCtx); - for (String key : selectedKeys) { - InfoboxAssocArrayPairType infoboxAssocArrayPairType = objectFactory.createInfoboxAssocArrayPairType(); - infoboxAssocArrayPairType.setKey(key); - Object value = values.get(key); - if (value instanceof byte[]) { - infoboxAssocArrayPairType.setBase64Content((byte[]) value); - } else { - infoboxAssocArrayPairType.setXMLContent((XMLContentType) value); - } - infoboxReadDataAssocArrayType.getPair().add(infoboxAssocArrayPairType); - } - - return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); + return new InfoboxReadResultImpl(marshallPairs(selectedKeys, getValues( + selectedKeys, cmdCtx), readPairs.isValuesAreXMLEntities())); } - + /** * Read the value specified by readPairs. * @@ -213,12 +203,7 @@ public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl protected InfoboxReadResult readValue(ReadValue readValue, SLCommandContext cmdCtx) throws SLCommandException { if (readValue.isValueIsXMLEntity() && !isValuesAreXMLEntities()) { - log.info("Got valuesAreXMLEntities=" + readValue + " but infobox type is binary."); - throw new SLCommandException(4010); - } - - if (!readValue.isValueIsXMLEntity() && isValuesAreXMLEntities()) { - log.info("Got valuesAreXMLEntities=" + readValue + " but infobox type is XML."); + log.info("Got valuesAreXMLEntities=" + readValue.isValueIsXMLEntity() + " but infobox type is binary."); throw new SLCommandException(4010); } @@ -230,24 +215,59 @@ public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl selectedKeys = Collections.emptyList(); } + return new InfoboxReadResultImpl(marshallPairs(selectedKeys, getValues( + selectedKeys, cmdCtx), readValue.isValueIsXMLEntity())); + + } + + protected InfoboxReadDataAssocArrayType marshallPairs(List selectedKeys, Map values, boolean areXMLEntities) throws SLCommandException { + ObjectFactory objectFactory = new ObjectFactory(); - + InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory.createInfoboxReadDataAssocArrayType(); - Map values = getValues(selectedKeys, cmdCtx); for (String key : selectedKeys) { InfoboxAssocArrayPairType infoboxAssocArrayPairType = objectFactory.createInfoboxAssocArrayPairType(); infoboxAssocArrayPairType.setKey(key); + Object value = values.get(key); - if (value instanceof byte[]) { - infoboxAssocArrayPairType.setBase64Content((byte[]) value); + if (areXMLEntities) { + if (value instanceof byte[]) { + log.info("Got valuesAreXMLEntities=" + areXMLEntities + " but infobox type is binary."); + throw new SLCommandException(4122); + } else { + XMLContentType contentType = objectFactory.createXMLContentType(); + contentType.getContent().add(value); + infoboxAssocArrayPairType.setXMLContent(contentType); + } } else { - infoboxAssocArrayPairType.setXMLContent((XMLContentType) value); + infoboxAssocArrayPairType.setBase64Content((value instanceof byte[]) ? (byte[]) value : marshallValue(value)); } + infoboxReadDataAssocArrayType.getPair().add(infoboxAssocArrayPairType); } + + return infoboxReadDataAssocArrayType; - return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); + } + + protected byte[] marshallValue(Object jaxbElement) throws SLCommandException { + SLCommandFactory commandFactory = SLCommandFactory.getInstance(); + JAXBContext jaxbContext = commandFactory.getJaxbContext(); + + ByteArrayOutputStream result; + try { + Marshaller marshaller = jaxbContext.createMarshaller(); + + result = new ByteArrayOutputStream(); + marshaller.marshal(jaxbElement, result); + } catch (JAXBException e) { + log.info("Failed to marshall infobox content.", e); + throw new SLCommandException(4122); + } + + return result.toByteArray(); + } @Override diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImpl.java new file mode 100644 index 00000000..7e204632 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImpl.java @@ -0,0 +1,323 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.slcommands.impl; + +import iaik.asn1.ASN; +import iaik.asn1.ASN1Object; +import iaik.asn1.CodingException; +import iaik.asn1.DerCoder; +import iaik.asn1.NumericString; +import iaik.asn1.OCTET_STRING; +import iaik.asn1.ObjectID; +import iaik.asn1.SEQUENCE; +import iaik.asn1.SET; +import iaik.asn1.UNKNOWN; +import iaik.asn1.structures.ChoiceOfTime; + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.buergerkarte.namespaces.cardchannel.AttributeList; +import at.buergerkarte.namespaces.cardchannel.AttributeType; +import at.buergerkarte.namespaces.cardchannel.ObjectFactory; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.InfoboxReadResponse; +import at.gv.egiz.stal.STALRequest; + +/** + * An implementation of the {@link Infobox} Certificates as + * specified in Security Layer 1.2. + * + * @author mcentner + */ +public class SVPersonendatenInfoboxImpl extends AbstractAssocArrayInfobox { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(SVPersonendatenInfoboxImpl.class); + + public static final String EHIC = "EHIC"; + + public static final String GRUNDDATEN = "Grunddaten"; + + public static final String STATUS = "Status"; + + public static final String SV_PERSONENBINDUNG = "SV-Personenbindung"; + + /** + * The valid keys. + */ + public static final String[] KEYS = new String[] { + GRUNDDATEN, EHIC, STATUS, SV_PERSONENBINDUNG + }; + + @Override + public String getIdentifier() { + return "SV-Personendaten"; + } + + @Override + public String[] getKeys() { + return KEYS; + } + + @Override + public boolean isValuesAreXMLEntities() { + return true; + } + + @Override + public Map getValues(List keys, SLCommandContext cmdCtx) throws SLCommandException { + + STALHelper stalHelper = new STALHelper(cmdCtx.getSTAL()); + + if (keys != null && !keys.isEmpty()) { + + List stalRequests = new ArrayList(); + + // get values + InfoboxReadRequest infoboxReadRequest; + for (int i = 0; i < keys.size(); i++) { + infoboxReadRequest = new InfoboxReadRequest(); + infoboxReadRequest.setInfoboxIdentifier(keys.get(i)); + stalRequests.add(infoboxReadRequest); + } + + stalHelper.transmitSTALRequest(stalRequests); + + Map values = new HashMap(); + + try { + for (int i = 0; i < keys.size(); i++) { + + String key = keys.get(i); + InfoboxReadResponse nextResponse = (InfoboxReadResponse) stalHelper.nextResponse(InfoboxReadResponse.class); + + + ObjectFactory objectFactory = new ObjectFactory(); + + if (EHIC.equals(key)) { + AttributeList attributeList = createAttributeList(nextResponse.getInfoboxValue()); + values.put(key, objectFactory.createEHIC(attributeList)); + } else if (GRUNDDATEN.equals(key)) { + AttributeList attributeList = createAttributeList(nextResponse.getInfoboxValue()); + values.put(key, objectFactory.createGrunddaten(attributeList)); + } else if (SV_PERSONENBINDUNG.equals(key)) { + values.put(key, objectFactory.createSVPersonenbindung(nextResponse.getInfoboxValue())); + } else if (STATUS.equals(key)) { + AttributeList attributeList = createAttributeListFromRecords(nextResponse.getInfoboxValue()); + values.put(key, objectFactory.createStatus(attributeList)); + } + + } + } catch (CodingException e) { + log.info("Failed to decode '" + getIdentifier() + "' infobox.", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, + new Object[] { "IdentityLink" }); + + } + + return values; + + } else { + + return new HashMap(); + + } + + + } + + public static AttributeList createAttributeList(byte[] infoboxValue) throws CodingException { + + ObjectFactory objectFactory = new ObjectFactory(); + + ASN1Object asn1 = DerCoder.decode(infoboxValue); + + AttributeList attributeList = objectFactory.createAttributeList(); + List attributes = attributeList.getAttribute(); + + if (asn1.isA(ASN.SEQUENCE)) { + for (int i = 0; i < ((SEQUENCE) asn1).countComponents(); i++) { + + AttributeType attributeType = objectFactory.createAttributeType(); + + if (asn1.getComponentAt(i).isA(ASN.SEQUENCE)) { + SEQUENCE attribute = (SEQUENCE) asn1.getComponentAt(i); + if (attribute.getComponentAt(0).isA(ASN.ObjectID)) { + ObjectID objectId = (ObjectID) attribute.getComponentAt(0); + attributeType.setOid("urn:oid:" + objectId.getID()); + } + if (attribute.getComponentAt(1).isA(ASN.SET)) { + SET values = (SET) attribute.getComponentAt(1); + for (int j = 0; j < values.countComponents(); j++) { + setAttributeValue(attributeType, values.getComponentAt(j)); + } + } + } + + attributes.add(attributeType); + + } + + } + + return attributeList; + + } + + public static AttributeList createAttributeListFromRecords(byte[] infoboxValue) throws CodingException { + + ObjectFactory objectFactory = new ObjectFactory(); + + AttributeList attributeList = objectFactory.createAttributeList(); + List attributes = attributeList.getAttribute(); + + byte[] records = infoboxValue; + + while (records != null && records.length > 0) { + + int length; + + if (records[0] != 0x00) { + + ASN1Object asn1 = DerCoder.decode(records); + + AttributeType attributeType = objectFactory.createAttributeType(); + + if (asn1.isA(ASN.SEQUENCE)) { + SEQUENCE attribute = (SEQUENCE) asn1; + if (attribute.getComponentAt(0).isA(ASN.ObjectID)) { + ObjectID objectId = (ObjectID) attribute.getComponentAt(0); + attributeType.setOid("urn:oid:" + objectId.getID()); + } + if (attribute.getComponentAt(1).isA(ASN.SET)) { + SET values = (SET) attribute.getComponentAt(1); + for (int j = 0; j < values.countComponents(); j++) { + setAttributeValue(attributeType, values.getComponentAt(j)); + } + } + } + + attributes.add(attributeType); + + length = DerCoder.encode(asn1).length; + + } else { + length = 1; + } + + if (length < records.length) { + records = Arrays.copyOfRange(records, length + 1, records.length); + } else { + records = null; + } + + } + + return attributeList; + + } + + private static void setAttributeValue(AttributeType attributeType, ASN1Object value) { + + if (value.isA(ASN.OCTET_STRING)) { + + try { + byte[] octets = ((OCTET_STRING) value).getWholeValue(); + attributeType.setLatin1String(new String(octets, Charset.forName("ISO-8859-1"))); + } catch (IOException e) { + log.info("Failed to set Latin1String.", e); + } + + } else if (value.isA(ASN.NumericString)) { + + attributeType.setNumericString((String) ((NumericString) value).getValue()); + + } else if (value.isA(ASN.GeneralizedTime)) { + + try { + ChoiceOfTime choiceOfTime = new ChoiceOfTime(value); + + GregorianCalendar gregorianCalendar = new GregorianCalendar(); + gregorianCalendar.setTimeZone(TimeZone.getTimeZone("UTC")); + gregorianCalendar.setTime(choiceOfTime.getDate()); + + DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); + XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar(gregorianCalendar); + xmlGregorianCalendar.setTimezone(0); + + attributeType.setGeneralizedTime(xmlGregorianCalendar); + } catch (Exception e) { + log.info("Failed to set GeneralizedTime.", e); + } + + } else if (value.isA(ASN.INTEGER)) { + + attributeType.setInteger((BigInteger) value.getValue()); + + } else if (value.isA(ASN.UTF8String)) { + + attributeType.setUTF8String((String) value.getValue()); + + } else if (value.isA(ASN.PrintableString)) { + + attributeType.setPrintableString((String) value.getValue()); + + } else if (value.isA(ASN.UNKNOWN)) { + + byte[] bytes = (byte[]) ((UNKNOWN) value).getValue(); + + try { + BigInteger bigInteger = new BigInteger(bytes); + String string = bigInteger.toString(16); + + Date date = new SimpleDateFormat("yyyyMMdd").parse(string); + attributeType.setDate(new SimpleDateFormat("yyyy-MM-dd").format(date)); + } catch (Exception e) { + log.info("Failed to set Date.", e); + } + } + + } + + + + + +} diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java new file mode 100644 index 00000000..f9c60b86 --- /dev/null +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java @@ -0,0 +1,147 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.slcommands.impl; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import iaik.asn1.CodingException; + +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import at.buergerkarte.namespaces.cardchannel.AttributeList; +import at.buergerkarte.namespaces.cardchannel.ObjectFactory; +import at.gv.egiz.bku.slcommands.ErrorResult; +import at.gv.egiz.bku.slcommands.InfoboxReadCommand; +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLRequestException; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.dummy.DummySTAL; + +//@Ignore +public class SVPersonendatenInfoboxImplTest { + + private byte[] EHIC = new byte[] { + (byte) 0x30, (byte) 0x6b, (byte) 0x30, (byte) 0x12, (byte) 0x06, (byte) 0x08, (byte) 0x2a, (byte) 0x28, + (byte) 0x00, (byte) 0x0a, (byte) 0x01, (byte) 0x04, (byte) 0x01, (byte) 0x14, (byte) 0x31, (byte) 0x06, + (byte) 0x04, (byte) 0x04, (byte) 0x42, (byte) 0x47, (byte) 0x4b, (byte) 0x4b, (byte) 0x30, (byte) 0x12, + (byte) 0x06, (byte) 0x08, (byte) 0x2a, (byte) 0x28, (byte) 0x00, (byte) 0x0a, (byte) 0x01, (byte) 0x04, + (byte) 0x01, (byte) 0x15, (byte) 0x31, (byte) 0x06, (byte) 0x12, (byte) 0x04, (byte) 0x31, (byte) 0x33, + (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x22, (byte) 0x06, (byte) 0x08, (byte) 0x2a, (byte) 0x28, + (byte) 0x00, (byte) 0x0a, (byte) 0x01, (byte) 0x04, (byte) 0x01, (byte) 0x16, (byte) 0x31, (byte) 0x16, + (byte) 0x12, (byte) 0x14, (byte) 0x38, (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x30, (byte) 0x30, + (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x32, (byte) 0x33, (byte) 0x30, (byte) 0x30, + (byte) 0x34, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x35, (byte) 0x39, (byte) 0x30, (byte) 0x1d, + (byte) 0x06, (byte) 0x08, (byte) 0x2a, (byte) 0x28, (byte) 0x00, (byte) 0x0a, (byte) 0x01, (byte) 0x04, + (byte) 0x01, (byte) 0x17, (byte) 0x31, (byte) 0x11, (byte) 0x18, (byte) 0x0f, (byte) 0x32, (byte) 0x30, + (byte) 0x30, (byte) 0x35, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x31, (byte) 0x31, (byte) 0x32, + (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x5a + }; + + private static ApplicationContext appCtx; + + private SLCommandFactory factory; + + private STAL stal; + +// @BeforeClass + public static void setUpClass() { + appCtx = new ClassPathXmlApplicationContext("at/gv/egiz/bku/slcommands/testApplicationContext.xml"); + } + +// @Before + public void setUp() { + factory = SLCommandFactory.getInstance(); + stal = new DummySTAL(); + } + + @Test + public void testEHIC() throws SLCommandException, JAXBException, CodingException, IOException { + + AttributeList attributeList = SVPersonendatenInfoboxImpl.createAttributeList(EHIC); + + JAXBElement ehic = new ObjectFactory().createEHIC(attributeList); + + JAXBContext jaxbContext = SLCommandFactory.getInstance().getJaxbContext(); + + Marshaller marshaller = jaxbContext.createMarshaller(); + + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + + marshaller.marshal(ehic, System.out); + + } + + @Ignore + @Test + public void testInfboxReadRequest() throws SLCommandException, SLRuntimeException, SLRequestException { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.xml"); + assertNotNull(inputStream); + + SLCommandContext context = new SLCommandContext(); + context.setSTAL(stal); + SLCommand command = factory.createSLCommand(new StreamSource(inputStream), context); + assertTrue(command instanceof InfoboxReadCommand); + + SLResult result = command.execute(); + result.writeTo(new StreamResult(System.out)); + } + + @Ignore + @Test(expected=SLCommandException.class) + public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-1.xml"); + assertNotNull(inputStream); + + SLCommandContext context = new SLCommandContext(); + context.setSTAL(stal); + SLCommand command = factory.createSLCommand(new StreamSource(inputStream), context); + assertTrue(command instanceof InfoboxReadCommand); + } + + @Ignore + public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-2.xml"); + assertNotNull(inputStream); + + SLCommandContext context = new SLCommandContext(); + context.setSTAL(stal); + SLCommand command = factory.createSLCommand(new StreamSource(inputStream), context); + assertTrue(command instanceof InfoboxReadCommand); + + SLResult result = command.execute(); + assertTrue(result instanceof ErrorResult); + } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java index 2baff834..6d96599c 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -30,7 +30,6 @@ package at.gv.egiz.smcc; import java.nio.charset.Charset; -import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -110,41 +109,47 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { public byte[] getCertificate(KeyboxName keyboxName) throws SignatureCardException, InterruptedException { - byte[] aid; - byte[] efc; - int maxsize; - if (keyboxName == KeyboxName.SECURE_SIGNATURE_KEYPAIR) { - aid = AID_SIG; - efc = EF_C_CH_DS; - maxsize = EF_C_CH_DS_MAX_SIZE; - } else if (keyboxName == KeyboxName.CERITIFIED_KEYPAIR) { - aid = AID_DEC; - efc = EF_C_CH_EKEY; - maxsize = EF_C_CH_EKEY_MAX_SIZE; - } else { - throw new IllegalArgumentException("Keybox " + keyboxName - + " not supported."); - } - - log.debug("Get certificate for keybox '" + keyboxName.getKeyboxName() + "'" + - " (AID=" + toString(aid) + " EF=" + toString(efc) + ")."); - try { - Card card = getCardChannel().getCard(); - try { - card.beginExclusive(); - return readTLVFile(aid, efc, maxsize + 15000); - } catch (FileNotFoundException e) { - // if certificate is not present, - // the citizen card application has not been activated - throw new NotActivatedException(); - } finally { - card.endExclusive(); + + if (keyboxName == KeyboxName.SECURE_SIGNATURE_KEYPAIR) { + + try { + getCard().beginExclusive(); + byte[] certificate = readTLVFile(AID_SIG, EF_C_CH_DS, EF_C_CH_DS_MAX_SIZE); + if (certificate == null) { + throw new NotActivatedException(); + } + return certificate; + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } finally { + getCard().endExclusive(); + } + + } else if (keyboxName == KeyboxName.CERITIFIED_KEYPAIR) { + + try { + getCard().beginExclusive(); + byte[] certificate = readTLVFile(AID_DEC, EF_C_CH_EKEY, EF_C_CH_EKEY_MAX_SIZE); + if (certificate == null) { + throw new NotActivatedException(); + } + return certificate; + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } finally { + getCard().endExclusive(); + } + + } else { + throw new IllegalArgumentException("Keybox " + keyboxName + + " not supported."); } + } catch (CardException e) { - throw new SignatureCardException("Failed to get exclusive card access."); + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); } - } @@ -155,30 +160,47 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { public byte[] getInfobox(String infobox, PINProvider provider, String domainId) throws SignatureCardException, InterruptedException { - if ("IdentityLink".equals(infobox)) { - - PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name")); - - try { - Card card = getCardChannel().getCard(); - try { - card.beginExclusive(); - return readTLVFilePIN(AID_DEC, EF_INFOBOX, KID_PIN_INF, provider, - spec, EF_INFOBOX_MAX_SIZE); - } catch (FileNotFoundException e) { - // if certificate is not present, - // the citizen card application has not been activated - throw new NotActivatedException(); - } finally { - card.endExclusive(); - } - } catch (CardException e) { - throw new SignatureCardException("Failed to get exclusive card access."); + try { + if ("IdentityLink".equals(infobox)) { + + PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name")); + + int retries = -1; + String pin = null; + boolean pinRequiered = false; + + do { + if (pinRequiered) { + pin = provider.providePIN(spec, retries); + if (pin == null) { + throw new CancelledException(); + } + } + try { + getCard().beginExclusive(); + return readTLVFile(AID_DEC, EF_INFOBOX, pin, KID_PIN_INF, EF_INFOBOX_MAX_SIZE); + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } catch (SecurityStatusNotSatisfiedException e) { + pinRequiered = true; + } catch (VerificationFailedException e) { + pinRequiered = true; + retries = e.getRetries(); + } finally { + getCard().endExclusive(); + } + } while (retries != 0); + + throw new LockedException(); + + } else { + throw new IllegalArgumentException("Infobox '" + infobox + + "' not supported."); } - - } else { - throw new IllegalArgumentException("Infobox '" + infobox - + "' not supported."); + + } catch (CardException e) { + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); } } @@ -192,68 +214,103 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } try { - Card card = getCardChannel().getCard(); - try { - card.beginExclusive(); - - if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { - - // SELECT DF - selectFileFID(DF_SIG); - // VERIFY - verifyPIN(provider, new PINSpec(6, 10, "[0-9]", getResourceBundle() - .getString("sig.pin.name")), KID_PIN_SIG); - // MSE: SET DST - mseSetDST(0x81, 0xb6, DST_SIG); - // PSO: HASH - psoHash(hash); - // PSO: COMPUTE DIGITAL SIGNATURE - return psoComputDigitalSiganture(); - } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { - - // SELECT DF - selectFileFID(DF_DEC); - // VERIFY - verifyPIN(provider, new PINSpec(4, 4, "[0-9]", getResourceBundle() - .getString("dec.pin.name")), KID_PIN_DEC); - // MSE: SET DST - mseSetDST(0x41, 0xa4, DST_DEC); - // INTERNAL AUTHENTICATE - return internalAuthenticate(hash); - - - // 00 88 10 00 23 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 54 26 F0 EA AF EA F0 4E D4 A1 AD BF 66 D4 A5 9B 45 6F AF 79 00 - // 00 88 10 00 23 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 DF 8C AB 8F E2 AD AC 7B 5A AF BE E9 44 5E 95 99 FA AF 2F 48 00 - - } else { - throw new IllegalArgumentException("KeyboxName '" + keyboxName - + "' not supported."); - } + if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { + + PINSpec spec = new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); + + int retries = -1; + String pin = null; + + do { + pin = provider.providePIN(spec, retries); + if (pin == null) { + throw new CancelledException(); + } + try { + getCard().beginExclusive(); + + // SELECT DF + selectFileFID(DF_SIG); + // VERIFY + retries = verifyPIN(pin, KID_PIN_SIG); + if (retries != -1) { + throw new VerificationFailedException(retries); + } + // MSE: SET DST + mseSetDST(0x81, 0xb6, DST_SIG); + // PSO: HASH + psoHash(hash); + // PSO: COMPUTE DIGITAL SIGNATURE + return psoComputDigitalSiganture(); + + } catch (SecurityStatusNotSatisfiedException e) { + retries = verifyPIN(null, KID_PIN_SIG); + } catch (VerificationFailedException e) { + retries = e.getRetries(); + } finally { + getCard().endExclusive(); + } + } while (retries != 0); + + throw new LockedException(); + + + } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { - } catch (FileNotFoundException e) { - // if certificate is not present, - // the citizen card application has not been activated - throw new NotActivatedException(); - } finally { - card.endExclusive(); + PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name")); + + int retries = -1; + String pin = null; + boolean pinRequiered = false; + + do { + if (pinRequiered) { + pin = provider.providePIN(spec, retries); + if (pin == null) { + throw new CancelledException(); + } + } + try { + getCard().beginExclusive(); + + // SELECT DF + selectFileFID(DF_DEC); + // VERIFY + retries = verifyPIN(pin, KID_PIN_DEC); + if (retries != -1) { + throw new VerificationFailedException(retries); + } + // MSE: SET DST + mseSetDST(0x41, 0xa4, DST_DEC); + // INTERNAL AUTHENTICATE + return internalAuthenticate(hash); + + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } catch (SecurityStatusNotSatisfiedException e) { + pinRequiered = true; + retries = verifyPIN(null, KID_PIN_DEC); + } catch (VerificationFailedException e) { + pinRequiered = true; + retries = e.getRetries(); + } finally { + getCard().endExclusive(); + } + } while (retries != 0); + + throw new LockedException(); + + } else { + throw new IllegalArgumentException("KeyboxName '" + keyboxName + + "' not supported."); } + } catch (CardException e) { - throw new SignatureCardException("Failed to get exclusive card access."); - } - - } - - protected byte[] selectFileAID(byte[] fid) throws CardException, SignatureCardException { - CardChannel channel = getCardChannel(); - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x04, - 0x00, fid, 256)); - if (resp.getSW() != 0x9000) { - throw new SignatureCardException("Failed to select file (AID=" - + toString(fid) + "): SW=" + Integer.toHexString(resp.getSW()) + "."); - } else { - return resp.getBytes(); - } + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); + } + } protected ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException { @@ -262,6 +319,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { 0x00, fid, 256)); } + @Override protected int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); @@ -290,35 +348,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } - /** - * - * @param pinProvider - * @param spec - * the PIN spec to be given to the pinProvider - * @param kid - * the KID (key identifier) of the PIN to be verified - * @throws CancelledException - * if the user canceld the operation - * @throws javax.smartcardio.CardException - * @throws at.gv.egiz.smcc.SignatureCardException - */ - @Override - protected void verifyPIN(PINProvider pinProvider, PINSpec spec, byte kid) - throws CardException, CancelledException, SignatureCardException, InterruptedException { - - int retries = -1; - do { - String pin = pinProvider.providePIN(spec, retries); - if (pin == null) { - // user canceled operation - throw new CancelledException("User canceled operation"); - } - retries = verifyPIN(pin, kid); - } while (retries > 0); - - } - - void mseSetDST(int p1, int p2, byte[] dst) throws CardException, SignatureCardException { + private void mseSetDST(int p1, int p2, byte[] dst) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0x22, p1, p2, dst)); @@ -328,7 +358,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } } - void psoHash(byte[] hash) throws CardException, SignatureCardException { + private void psoHash(byte[] hash) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0x2A, 0x90, 0x81, hash)); @@ -338,7 +368,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } } - byte[] psoComputDigitalSiganture() throws CardException, + private byte[] psoComputDigitalSiganture() throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0x2A, 0x9E, @@ -352,7 +382,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } } - byte[] internalAuthenticate(byte[] hash) throws CardException, SignatureCardException { + private byte[] internalAuthenticate(byte[] hash) throws CardException, SignatureCardException { byte[] digestInfo = new byte[] { (byte) 0x30, (byte) 0x21, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x05, (byte) 0x2B, (byte) 0x0E, (byte) 0x03, (byte) 0x02, (byte) 0x1A, (byte) 0x05, (byte) 0x00, (byte) 0x04 diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java index e34c4899..633cc90d 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -28,6 +28,8 @@ // package at.gv.egiz.smcc; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.util.Locale; import java.util.ResourceBundle; @@ -79,45 +81,56 @@ public abstract class AbstractSignatureCard implements SignatureCard { return sb.toString(); } - protected abstract byte[] selectFileAID(byte[] fid) throws CardException, - SignatureCardException; - - protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, - SignatureCardException; - /** - * VERIFY PIN + * Select an application using AID as DF name according to ISO/IEC 7816-4 + * section 8.2.2.2. * - *

- * Implementations of this method should call - * {@link PINProvider#providePIN(PINSpec, int)} to retrieve the PIN entered by - * the user and VERIFY PIN on the smart card until the PIN has been - * successfully verified. - *

+ * @param dfName + * AID of the application to be selected * - * @param pinProvider - * the PINProvider - * @param spec - * the PINSpec - * @param kid - * the key ID (KID) of the PIN to verify + * @return the response data of the response APDU if SW=0x9000 * * @throws CardException - * if smart card communication fails - * - * @throws CancelledException - * if the PINProvider indicated that the user canceled the PIN entry - * @throws NotActivatedException - * if the card application has not been activated - * @throws LockedException - * if the card application is locked + * if card communication fails * * @throws SignatureCardException - * if VERIFY PIN fails + * if application selection fails (e.g. an application with the + * given AID is not present on the card) */ - protected abstract void verifyPIN(PINProvider pinProvider, PINSpec spec, - byte kid) throws CardException, SignatureCardException, InterruptedException; + protected byte[] selectFileAID(byte[] dfName) throws CardException, SignatureCardException { + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x04, + 0x00, dfName, 256)); + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("Failed to select application AID=" + + toString(dfName) + ": SW=" + Integer.toHexString(resp.getSW()) + "."); + } else { + return resp.getBytes(); + } + } + + protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, + SignatureCardException; + protected abstract int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException; + + + protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { + return readRecord(getCardChannel(), recordNumber); + } + + protected byte[] readRecord(CardChannel channel, int recordNumber) throws SignatureCardException, CardException { + + ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB2, + recordNumber, 0x04, 256)); + if (resp.getSW() == 0x9000) { + return resp.getData(); + } else { + throw new SignatureCardException("Failed to read records. SW=" + Integer.toHexString(resp.getSW())); + } + + } + protected byte[] readBinary(CardChannel channel, int offset, int len) throws CardException, SignatureCardException { @@ -125,6 +138,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { 0x7F & (offset >> 8), offset & 0xFF, len)); if (resp.getSW() == 0x9000) { return resp.getData(); + } else if (resp.getSW() == 0x6982) { + throw new SecurityStatusNotSatisfiedException(); } else { throw new SignatureCardException("Failed to read bytes (" + offset + "+" + len + "): SW=" + Integer.toHexString(resp.getSW())); @@ -188,43 +203,10 @@ public abstract class AbstractSignatureCard implements SignatureCard { } - /** - * Read the content of a TLV file. - * - * @param aid the application ID (AID) - * @param ef the elementary file (EF) - * @param maxLength the maximum length of the file - * - * @return the content of the file - * - * @throws SignatureCardException - */ - protected byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) - throws SignatureCardException, InterruptedException { - return readTLVFilePIN(aid, ef, (byte) 0, null, null, maxLength); - } - - - /** - * Read the content of a TLV file wich may require a PIN. - * - * @param aid the application ID (AID) - * @param ef the elementary file (EF) - * @param kid the key ID (KID) of the corresponding PIN - * @param provider the PINProvider - * @param spec the PINSpec - * @param maxLength the maximum length of the file - * - * @return the content of the file - * - * @throws SignatureCardException - */ - protected byte[] readTLVFilePIN(byte[] aid, byte[] ef, byte kid, - PINProvider provider, PINSpec spec, int maxLength) - throws SignatureCardException, InterruptedException { - + protected byte[] readRecords(byte[] aid, byte[] ef, int start, int end) throws SignatureCardException, InterruptedException { + try { - + // SELECT FILE (AID) byte[] rb = selectFileAID(aid); if (rb[rb.length - 2] != (byte) 0x90 || rb[rb.length - 1] != (byte) 0x00) { @@ -256,37 +238,89 @@ public abstract class AbstractSignatureCard implements SignatureCard { + Integer.toHexString(resp.getSW()) + ")."); } - - // try to READ BINARY - byte[] b = new byte[1]; - int sw = readBinary(0, 1, b); - if (provider != null && sw == 0x6982) { - - // VERIFY - verifyPIN(provider, spec, kid); - - } else if (sw == 0x9000) { - // not expected type - if (b[0] != 0x30) { - throw new NotActivatedException(); - } - } else { - throw new SignatureCardException("READ BINARY failed (SW=" - + Integer.toHexString(sw) + ")."); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + + for (int i = start; i <= end; i++) { + bytes.write(readRecord(i)); } - - // READ BINARY - byte[] data = readBinaryTLV(maxLength, (byte) 0x30); - - return data; - + + return bytes.toByteArray(); + } catch (CardException e) { throw new SignatureCardException("Failed to acces card.", e); + } catch (IOException e) { + throw new SignatureCardException("Failed to read records.", e); } - + + } + + /** + * Read the content of a TLV file. + * + * @param aid the application ID (AID) + * @param ef the elementary file (EF) + * @param maxLength the maximum length of the file + * + * @return the content of the file + * + * @throws SignatureCardException + * @throws CardException + */ + protected byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) + throws SignatureCardException, InterruptedException, CardException { + return readTLVFile(aid, ef, null, (byte) 0, maxLength); } + /** + * Read the content of a TLV file wich may require a PIN. + * + * @param aid the application ID (AID) + * @param ef the elementary file (EF) + * @param kid the key ID (KID) of the corresponding PIN + * @param provider the PINProvider + * @param spec the PINSpec + * @param maxLength the maximum length of the file + * + * @return the content of the file + * + * @throws SignatureCardException + * @throws CardException + */ + protected byte[] readTLVFile(byte[] aid, byte[] ef, String pin, byte kid, int maxLength) + throws SignatureCardException, InterruptedException, CardException { + + + // SELECT FILE (AID) + selectFileAID(aid); + + // SELECT FILE (EF) + ResponseAPDU resp = selectFileFID(ef); + if (resp.getSW() == 0x6a82) { + // EF not found + throw new FileNotFoundException("EF " + toString(ef) + " not found."); + } else if (resp.getSW() != 0x9000) { + throw new SignatureCardException("SELECT FILE with " + + "FID=" + + toString(ef) + + " failed (" + + "SW=" + + Integer.toHexString(resp.getSW()) + ")."); + } + + // VERIFY + if (pin != null) { + int retries = verifyPIN(pin, kid); + if (retries != -1) { + throw new VerificationFailedException(retries); + } + } + + return readBinaryTLV(maxLength, (byte) 0x30); + + + } + /** * Transmit the given command APDU using the given card channel. * diff --git a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java index d6d02475..2a6e90bf 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -31,7 +31,6 @@ package at.gv.egiz.smcc; import java.math.BigInteger; import java.util.Arrays; -import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -49,6 +48,42 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; + /** + * Application ID SV-Personendaten. + */ + public static final byte[] AID_SV_PERSONENDATEN = new byte[] { + (byte) 0xD0, (byte) 0x40, (byte) 0x00, (byte) 0x00, + (byte) 0x17, (byte) 0x01, (byte) 0x01, (byte) 0x01 + }; + + /** + * File ID Grunddaten ({@link #AID_SV_PERSONENDATEN}). + */ + public static final byte[] FID_GRUNDDATEN = new byte[] { + (byte) 0xEF, (byte) 0x01 + }; + + /** + * File ID EHIC ({@link #AID_SV_PERSONENDATEN}). + */ + public static final byte[] FID_EHIC = new byte[] { + (byte) 0xEF, (byte) 0x02 + }; + + /** + * File ID Status ({@link #AID_SV_PERSONENDATEN}). + */ + public static final byte[] FID_SV_PERSONENBINDUNG = new byte[] { + (byte) 0xEF, (byte) 0x03 + }; + + /** + * File ID Status ({@link #AID_SV_PERSONENDATEN}). + */ + public static final byte[] FID_STATUS = new byte[] { + (byte) 0xEF, (byte) 0x04 + }; + public static final byte[] AID_INFOBOX = new byte[] { (byte) 0xd0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x18, (byte) 0x01 }; @@ -126,85 +161,134 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard super("at/gv/egiz/smcc/STARCOSCard"); } - /* (non-Javadoc) - * @see at.gv.egiz.smcc.SignatureCard#getCertificate(at.gv.egiz.smcc.SignatureCard.KeyboxName) - */ @Override public byte[] getCertificate(KeyboxName keyboxName) throws SignatureCardException, InterruptedException { - byte[] aid; - byte[] efc; - if (keyboxName == KeyboxName.SECURE_SIGNATURE_KEYPAIR) { - aid = AID_DF_SS; - efc = EF_C_X509_CH_DS; - } else if (keyboxName == KeyboxName.CERITIFIED_KEYPAIR) { - aid = AID_DF_GS; - efc = EF_C_X509_CH_AUT; - } else { - throw new IllegalArgumentException("Keybox " + keyboxName - + " not supported."); - } + try { + + if (keyboxName == KeyboxName.SECURE_SIGNATURE_KEYPAIR) { + + try { + getCard().beginExclusive(); + return readTLVFile(AID_DF_SS, EF_C_X509_CH_DS, 2000); + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } finally { + getCard().endExclusive(); + } + + } else if (keyboxName == KeyboxName.CERITIFIED_KEYPAIR) { - log.debug("Get certificate for keybox '" + keyboxName.getKeyboxName() + "'" + - " (AID=" + toString(aid) + " EF=" + toString(efc) + ")."); + try { + getCard().beginExclusive(); + return readTLVFile(AID_DF_GS, EF_C_X509_CH_AUT, 2000); + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } finally { + getCard().endExclusive(); + } - try { - Card card = getCardChannel().getCard(); - try { - card.beginExclusive(); - return readTLVFile(aid, efc, 2000); - } catch (FileNotFoundException e) { - // if certificate is not present, - // the citizen card application has not been activated - throw new NotActivatedException(); - } finally { - card.endExclusive(); + } else { + throw new IllegalArgumentException("Keybox " + keyboxName + + " not supported."); } + } catch (CardException e) { - throw new SignatureCardException("Failed to get exclusive card access."); + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); } - - } - /* (non-Javadoc) - * @see at.gv.egiz.smcc.SignatureCard#getInfobox(java.lang.String, at.gv.egiz.smcc.PINProvider, java.lang.String) - */ + } + @Override public byte[] getInfobox(String infobox, PINProvider provider, String domainId) throws SignatureCardException, InterruptedException { - if ("IdentityLink".equals(infobox)) { - - PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); - - try { - Card card = getCardChannel().getCard(); + try { + if ("IdentityLink".equals(infobox)) { + + PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); + + int retries = -1; + String pin = null; + boolean pinRequiered = false; + + do { + if (pinRequiered) { + pin = provider.providePIN(spec, retries); + if (pin == null) { + throw new CancelledException(); + } + } + try { + getCard().beginExclusive(); + return readTLVFile(AID_INFOBOX, EF_INFOBOX, pin, KID_PIN_CARD, 2000); + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } catch (SecurityStatusNotSatisfiedException e) { + pinRequiered = true; + retries = verifyPIN(null, KID_PIN_CARD); + } catch (VerificationFailedException e) { + pinRequiered = true; + retries = e.getRetries(); + } finally { + getCard().endExclusive(); + } + } while (retries != 0); + + throw new LockedException(); + + + } else if ("EHIC".equals(infobox)) { + try { - card.beginExclusive(); - return readTLVFilePIN(AID_INFOBOX, EF_INFOBOX, KID_PIN_CARD, - provider, spec, 2000); - } catch (FileNotFoundException e) { - // if certificate is not present, - // the citizen card application has not been activated - throw new NotActivatedException(); + getCard().beginExclusive(); + return readTLVFile(AID_SV_PERSONENDATEN, FID_EHIC, 126); } finally { - card.endExclusive(); + getCard().endExclusive(); } - } catch (CardException e) { - throw new SignatureCardException("Failed to get exclusive card access."); + + } else if ("Grunddaten".equals(infobox)) { + + try { + getCard().beginExclusive(); + return readTLVFile(AID_SV_PERSONENDATEN, FID_GRUNDDATEN, 550); + } finally { + getCard().endExclusive(); + } + + } else if ("SV-Personenbindung".equals(infobox)) { + + try { + getCard().beginExclusive(); + return readTLVFile(AID_SV_PERSONENDATEN, FID_SV_PERSONENBINDUNG, 500); + } finally { + getCard().endExclusive(); + } + + } else if ("Status".equals(infobox)) { + + try { + getCard().beginExclusive(); + return readRecords(AID_SV_PERSONENDATEN, FID_STATUS, 1, 5); + } finally { + getCard().endExclusive(); + } + + } else { + throw new IllegalArgumentException("Infobox '" + infobox + + "' not supported."); } - } else { - throw new IllegalArgumentException("Infobox '" + infobox - + "' not supported."); + } catch (CardException e) { + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); } } - /* (non-Javadoc) - * @see at.gv.egiz.smcc.SignatureCard#createSignature(byte[], at.gv.egiz.smcc.SignatureCard.KeyboxName, at.gv.egiz.smcc.PINProvider) - */ + @Override public byte[] createSignature(byte[] hash, KeyboxName keyboxName, PINProvider provider) throws SignatureCardException, InterruptedException { @@ -212,72 +296,115 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard throw new IllegalArgumentException("Hash value must be of length 20."); } - byte[] aid; - byte kid; - byte[] dst; - PINSpec spec; - if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { - aid = AID_DF_SS; - kid = KID_PIN_SS; - dst = DST_SS; - spec = new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); - - } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { - aid = AID_DF_GS; - kid = KID_PIN_CARD; - dst = DST_GS; - spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); - - } else { - throw new IllegalArgumentException("KeyboxName '" + keyboxName - + "' not supported."); - } - try { - Card card = getCardChannel().getCard(); - try { - card.beginExclusive(); - - // SELECT MF - selectMF(); - // SELECT DF - selectFileAID(aid); - // VERIFY - verifyPIN(provider, spec, kid); - // MSE: SET DST - mseSetDST(dst); - // PSO: HASH - psoHash(hash); - // PSO: COMPUTE DIGITAL SIGNATURE - return psoComputDigitalSiganture(); - - - } catch (FileNotFoundException e) { - // if certificate is not present, - // the citizen card application has not been activated - throw new NotActivatedException(); - } finally { - card.endExclusive(); + + if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { + + PINSpec spec = new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); + + int retries = -1; + String pin = null; + + do { + try { + getCard().beginExclusive(); + selectFileAID(AID_DF_SS); + retries = verifyPIN(null, KID_PIN_SS); + } finally { + getCard().endExclusive(); + } + pin = provider.providePIN(spec, retries); + if (pin == null) { + throw new CancelledException(); + } + try { + getCard().beginExclusive(); + return createSignature(hash, AID_DF_SS, pin, KID_PIN_SS, DST_SS); + } catch (VerificationFailedException e) { + retries = e.getRetries(); + } finally { + getCard().endExclusive(); + } + } while (retries != 0); + + throw new LockedException(); + + + } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { + + PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); + + int retries = -1; + String pin = null; + boolean pinRequiered = false; + + do { + if (pinRequiered) { + pin = provider.providePIN(spec, retries); + if (pin == null) { + throw new CancelledException(); + } + } + try { + getCard().beginExclusive(); + return createSignature(hash, AID_DF_GS, pin, KID_PIN_CARD, DST_GS); + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } catch (SecurityStatusNotSatisfiedException e) { + pinRequiered = true; + retries = verifyPIN(null, KID_PIN_CARD); + } catch (VerificationFailedException e) { + pinRequiered = true; + retries = e.getRetries(); + } finally { + getCard().endExclusive(); + } + } while (retries != 0); + + throw new LockedException(); + + } else { + throw new IllegalArgumentException("KeyboxName '" + keyboxName + + "' not supported."); } + } catch (CardException e) { - throw new SignatureCardException("Failed to get exclusive card access."); + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); } } - protected byte[] selectFileAID(byte[] fid) throws CardException, SignatureCardException { + protected ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x04, + return transmit(channel, new CommandAPDU(0x00, 0xA4, 0x02, 0x04, fid, 256)); - if (resp.getSW() != 0x9000) { - throw new SignatureCardException("Failed to select file (AID=" - + toString(fid) + "): SW=" + Integer.toHexString(resp.getSW()) + "."); - } else { - return resp.getBytes(); + } + + private byte[] createSignature(byte[] hash, byte[] aid, String pin, byte kid, + byte[] dst) throws CardException, SignatureCardException { + + // SELECT MF + selectMF(); + // SELECT DF + selectFileAID(aid); + // VERIFY + int retries = verifyPIN(pin, kid); + if (retries != -1) { + throw new VerificationFailedException(retries); } + // MSE: SET DST + mseSetDST(dst); + // PSO: HASH + psoHash(hash); + // PSO: COMPUTE DIGITAL SIGNATURE + return psoComputDigitalSiganture(); + + } - void selectMF() throws CardException, SignatureCardException { + + private void selectMF() throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x00, 0x0C)); @@ -287,13 +414,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } } - protected ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException { - CardChannel channel = getCardChannel(); - return transmit(channel, new CommandAPDU(0x00, 0xA4, 0x02, - 0x04, fid, 256)); - } - - void mseSetDST(byte[] dst) throws CardException, SignatureCardException { + private void mseSetDST(byte[] dst) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0x22, 0x41, 0xB6, dst)); @@ -303,7 +424,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } } - void psoHash(byte[] hash) throws CardException, SignatureCardException { + private void psoHash(byte[] hash) throws CardException, SignatureCardException { byte[] data = new byte[hash.length + 2]; data[0] = (byte) 0x90; // tag data[1] = (byte) (hash.length); // length @@ -318,7 +439,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } } - byte[] psoComputDigitalSiganture() throws CardException, + private byte[] psoComputDigitalSiganture() throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0x2A, 0x9E, @@ -353,7 +474,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard * @throws SignatureCardException * if VERIFY PIN fails */ - private int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException { + @Override + protected int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); @@ -385,6 +507,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { // return number of possible retries return resp.getSW2() & 0x0f; + } else if (resp.getSW() == 0x6983) { + throw new LockedException(); } else if (resp.getSW() == 0x6984) { // PIN LCS = "Initialized" (-> not activated) throw new NotActivatedException("PIN not set."); @@ -397,26 +521,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } - /* (non-Javadoc) - * @see at.gv.egiz.smcc.AbstractSignatureCard#verifyPIN(at.gv.egiz.smcc.PINProvider, at.gv.egiz.smcc.PINSpec, byte, int) - */ - protected void verifyPIN(PINProvider pinProvider, PINSpec spec, byte kid) - throws CardException, SignatureCardException, InterruptedException { - - int retries = verifyPIN(null, kid); - do { - String pin = pinProvider.providePIN(spec, retries); - if (pin == null) { - // user canceled operation - throw new CancelledException("User canceld operation."); - } - retries = verifyPIN(pin, kid); - } while (retries > 0); - - } - public String toString() { - return "eCard"; + return "e-card"; } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SecurityStatusNotSatisfiedException.java b/smcc/src/main/java/at/gv/egiz/smcc/SecurityStatusNotSatisfiedException.java new file mode 100644 index 00000000..bf0af76c --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/SecurityStatusNotSatisfiedException.java @@ -0,0 +1,38 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc; + +public class SecurityStatusNotSatisfiedException extends SignatureCardException { + + private static final long serialVersionUID = 1L; + + public SecurityStatusNotSatisfiedException() { + } + + public SecurityStatusNotSatisfiedException(String message, Throwable cause) { + super(message, cause); + } + + public SecurityStatusNotSatisfiedException(String message) { + super(message); + } + + public SecurityStatusNotSatisfiedException(Throwable cause) { + super(cause); + } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/VerificationFailedException.java b/smcc/src/main/java/at/gv/egiz/smcc/VerificationFailedException.java new file mode 100644 index 00000000..fa066ff9 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/VerificationFailedException.java @@ -0,0 +1,65 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc; + +public class VerificationFailedException extends SignatureCardException { + + private static final long serialVersionUID = 1L; + + public static final int UNKNOWN = -1; + + private int retries = UNKNOWN; + + public VerificationFailedException() { + } + + public VerificationFailedException(String message, Throwable cause) { + super(message, cause); + } + + public VerificationFailedException(String message) { + super(message); + } + + public VerificationFailedException(Throwable cause) { + super(cause); + } + + public VerificationFailedException(int retries) { + this.retries = retries; + } + + public VerificationFailedException(int retries, String message, Throwable cause) { + super(message, cause); + this.retries = retries; + } + + public VerificationFailedException(int retries, String message) { + super(message); + this.retries = retries; + } + + public VerificationFailedException(int retries, Throwable cause) { + super(cause); + this.retries = retries; + } + + public int getRetries() { + return retries; + } + +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/STARCOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/STARCOSCardTest.java index 13210540..090e1181 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/STARCOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/STARCOSCardTest.java @@ -19,6 +19,8 @@ package at.gv.egiz.smcc; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Locale; @@ -27,6 +29,8 @@ import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; +import sun.misc.HexDumpEncoder; + import at.gv.egiz.smcc.SignatureCard.KeyboxName; import at.gv.egiz.smcc.util.SMCCHelper; @@ -34,10 +38,9 @@ public class STARCOSCardTest { /** * @param args - * @throws CardException - * @throws NoSuchAlgorithmException + * @throws Exception */ - public static void main(String[] args) throws CardException, NoSuchAlgorithmException, InterruptedException { + public static void main(String[] args) throws Exception { SMCCHelper helper = new SMCCHelper(); while (helper.getResultCode() != SMCCHelper.CARD_FOUND) { @@ -55,18 +58,41 @@ public class STARCOSCardTest { System.out.println("Found '" + signatureCard + "'."); try { -// signatureCard.getCertificate(KeyboxName.SECURE_SIGNATURE_KEYPAIR); -// signatureCard.getCertificate(KeyboxName.CERITIFIED_KEYPAIR); -// signatureCard.getInfobox("IdentityLink", new CommandLinePINProvider(), null); +// printJavaByteArray( +// signatureCard.getCertificate(KeyboxName.SECURE_SIGNATURE_KEYPAIR), System.out); +// printJavaByteArray( +// signatureCard.getCertificate(KeyboxName.CERITIFIED_KEYPAIR), System.out); +// System.out. println(new String(signatureCard.getInfobox("IdentityLink", new CommandLinePINProvider(), null))); +// byte[] infobox = signatureCard.getInfobox("Status", new CommandLinePINProvider(), null); +// printJavaByteArray(infobox, System.out); MessageDigest messageDigest = MessageDigest.getInstance("SHA-1"); byte[] digest = messageDigest.digest("test".getBytes()); - signatureCard.createSignature(digest, KeyboxName.CERITIFIED_KEYPAIR, new CommandLinePINProvider()); + byte[] signature = signatureCard.createSignature(digest, KeyboxName.SECURE_SIGNATURE_KEYPAIR, new CommandLinePINProvider()); + printJavaByteArray(signature, System.out); } catch (SignatureCardException e) { e.printStackTrace(); } } + public static void printJavaByteArray(byte[] bytes, OutputStream os) { + + PrintWriter w = new PrintWriter(os); + + w.write("new byte[] {"); + for (int i = 0; i < bytes.length;) { + if (i % 8 == 0) { + w.write("\n "); + } + w.write("(byte) 0x" + Integer.toHexString(0x0F & (bytes[i] >> 4)) + Integer.toHexString(0x0F & bytes[i])); + if (++i < bytes.length) { + w.write(", "); + } + } + w.write("\n};"); + w.flush(); + } + private static class CommandLinePINProvider implements PINProvider { @Override diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java index 04f179e7..5a54e97f 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java @@ -103,6 +103,9 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements stalResp.setInfoboxValue(resp); return stalResp; } + } catch (IllegalArgumentException e) { + log.info("Infobox " + infoBox.getInfoboxIdentifier() + " not supported."); + return new ErrorResponse(4002); } catch (NotActivatedException e) { log.info("Citizen card not activated.", e); gui.showErrorDialog(BKUGUIFacade.ERR_CARD_NOTACTIVATED, null, this, null); -- cgit v1.2.3 From 54aa4703e3d66c5b1a63b8d925fd4c9c1766687c Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 28 Jan 2009 19:40:11 +0000 Subject: activation git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@291 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- BKUApplet/pom.xml | 74 +- .../gv/egiz/bku/online/applet/AppletBKUWorker.java | 74 +- .../bku/online/applet/AppletParameterProvider.java | 57 -- .../at/gv/egiz/bku/online/applet/BKUApplet.java | 106 ++- BKUApplet/src/test/resources/appletTest.html | 2 +- BKULocal/pom.xml | 2 +- .../at/gv/egiz/bku/local/stal/LocalBKUWorker.java | 1 - BKULocalApp/pom.xml | 6 +- BKUOnline/pom.xml | 108 ++- .../egiz/bku/online/webapp/BKURequestHandler.java | 3 + .../stal/service/impl/STALRequestBrokerImpl.java | 8 +- .../gv/egiz/stal/service/impl/STALServiceImpl.java | 18 +- .../stal/service/impl/STALXJAXBContextFactory.java | 10 +- BKUOnline/src/main/webapp/applet.jsp | 14 +- BKUOnline/src/main/webapp/slRequestForm.html | 3 +- STALExt/pom.xml | 2 +- .../java/at/gv/egiz/stal/service/STALPortType.java | 2 +- .../stal/service/translator/STALTranslator.java | 5 +- STALXService/pom.xml | 25 + .../namespaces/cardchannel/service/ATRType.java | 100 +++ .../cardchannel/service/AttributeList.java | 71 ++ .../cardchannel/service/AttributeType.java | 264 +++++++ .../cardchannel/service/CommandAPDUType.java | 154 ++++ .../cardchannel/service/ObjectFactory.java | 172 +++++ .../namespaces/cardchannel/service/ResetType.java | 64 ++ .../cardchannel/service/ResponseAPDUType.java | 161 +++++ .../cardchannel/service/ResponseType.java | 82 +++ .../namespaces/cardchannel/service/ScriptType.java | 85 +++ .../cardchannel/service/VerifyAPDUType.java | 266 +++++++ .../cardchannel/service/package-info.java | 2 + .../at/gv/egiz/stalx/service/STALPortType.java | 45 ++ .../java/at/gv/egiz/stalx/service/STALService.java | 73 ++ .../translator/STALXTranslationHandler.java | 217 ++++++ .../src/main/resources/wsdl/CardChannel.xsd | 148 ++++ STALXService/src/main/resources/wsdl/stal.xsd | 162 +++++ STALXService/src/main/resources/wsdl/stalx.wsdl | 123 ++++ .../stalx/service/ClientJAXBContextFactory.java | 52 ++ .../at/gv/egiz/stalx/service/STALServiceTest.java | 112 +++ bkucommon/pom.xml | 7 +- .../slcommands/impl/AbstractAssocArrayInfobox.java | 6 +- .../impl/CreateXMLSignatureResultImpl.java | 145 ++-- .../slcommands/impl/InfoboxReadResultFileImpl.java | 197 ++--- .../gv/egiz/bku/slcommands/impl/SLResultImpl.java | 6 +- pom.xml | 7 + .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 5 +- utils/pom.xml | 5 + .../egiz/idlink/CompressedIdentityLinkFactory.java | 800 ++++++++++----------- .../at/gv/egiz/idlink/IdentityLinkFactory.java | 6 +- .../java/at/gv/egiz/marshal/MarshallerFactory.java | 52 ++ .../gv/egiz/marshal/NamespacePrefixMapperImpl.java | 86 +++ .../gv/egiz/xades/QualifyingPropertiesFactory.java | 418 +++++------ 51 files changed, 3519 insertions(+), 1094 deletions(-) delete mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletParameterProvider.java create mode 100644 STALXService/pom.xml create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/ATRType.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/AttributeList.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/AttributeType.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/CommandAPDUType.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/ObjectFactory.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/ResetType.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/ResponseAPDUType.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/ResponseType.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/ScriptType.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/VerifyAPDUType.java create mode 100644 STALXService/src/main/java/at/buergerkarte/namespaces/cardchannel/service/package-info.java create mode 100644 STALXService/src/main/java/at/gv/egiz/stalx/service/STALPortType.java create mode 100644 STALXService/src/main/java/at/gv/egiz/stalx/service/STALService.java create mode 100644 STALXService/src/main/java/at/gv/egiz/stalx/service/translator/STALXTranslationHandler.java create mode 100644 STALXService/src/main/resources/wsdl/CardChannel.xsd create mode 100644 STALXService/src/main/resources/wsdl/stal.xsd create mode 100644 STALXService/src/main/resources/wsdl/stalx.wsdl create mode 100644 STALXService/src/test/java/at/gv/egiz/stalx/service/ClientJAXBContextFactory.java create mode 100644 STALXService/src/test/java/at/gv/egiz/stalx/service/STALServiceTest.java create mode 100644 utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java create mode 100644 utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java (limited to 'smccSTAL/src') diff --git a/BKUApplet/pom.xml b/BKUApplet/pom.xml index 3b115399..da5dbc6f 100644 --- a/BKUApplet/pom.xml +++ b/BKUApplet/pom.xml @@ -23,35 +23,23 @@ at.gv.egiz true ${project.build.outputDirectory} - META-INF\/ + META-INF\/ + + + + + copy_testapplet + + copy-dependencies + + + ${project.build.directory}/test-classes + at.gv.egiz,commons-logging,iaik + commons-logging,iaik_jce_me4se + true + @@ -80,30 +68,6 @@ true - - maven-dependency-plugin - - - copytestlibs - - copy - - - - - commons-logging - commons-logging - - - iaik - iaik_jce_me4se - - - ${project.build.directory}/test-libs - - - - @@ -132,9 +96,5 @@ BKUCommonGUI 1.0.5-SNAPSHOT - - commons-logging - commons-logging - \ No newline at end of file diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java index 6ac892ec..388f045f 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java @@ -22,7 +22,6 @@ import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; import at.gv.egiz.stal.service.STALPortType; -import at.gv.egiz.stal.service.STALService; import at.gv.egiz.stal.service.translator.STALTranslator; import at.gv.egiz.stal.service.translator.TranslationException; import at.gv.egiz.stal.service.types.ErrorResponseType; @@ -31,13 +30,10 @@ import at.gv.egiz.stal.service.types.GetNextRequestType; import at.gv.egiz.stal.service.types.ObjectFactory; import at.gv.egiz.stal.service.types.RequestType; import at.gv.egiz.stal.service.types.ResponseType; -import java.applet.AppletContext; import java.net.MalformedURLException; -import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.xml.bind.JAXBElement; -import javax.xml.namespace.QName; import javax.xml.ws.WebServiceException; /** @@ -46,29 +42,19 @@ import javax.xml.ws.WebServiceException; */ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { - protected AppletContext ctx; - protected AppletParameterProvider params; + protected BKUApplet applet; protected String sessionId; - protected STALPortType stalPort; + private ObjectFactory stalObjFactory = new ObjectFactory(); - private STALTranslator translator = new STALTranslator(); - public AppletBKUWorker(BKUGUIFacade gui, AppletContext ctx, - AppletParameterProvider paramProvider) { + public AppletBKUWorker(BKUApplet applet, BKUGUIFacade gui) { super(gui); - if (ctx == null) { - throw new NullPointerException("Applet context not provided"); - } - if (paramProvider == null) { - throw new NullPointerException("No applet parameters provided"); - } - this.ctx = ctx; - this.params = paramProvider; - - sessionId = params.getAppletParameter(BKUApplet.SESSION_ID); + this.applet = applet; + + sessionId = applet.getParameter(BKUApplet.SESSION_ID); if (sessionId == null) { sessionId = "TestSession"; - log.info("using dummy sessionId " + sessionId); + log.warn("using dummy sessionId " + sessionId); } } @@ -77,9 +63,11 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { gui.showWelcomeDialog(); try { - stalPort = getSTALPort(); + STALPortType stalPort = applet.getSTALPort(); + STALTranslator stalTranslator = applet.getSTALTranslator(); - registerSignRequestHandler(stalPort, sessionId); + addRequestHandler(SignRequest.class, + new AppletHashDataDisplay(stalPort, sessionId)); GetNextRequestResponseType nextRequestResp = stalPort.connect(sessionId); @@ -111,7 +99,7 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { List stalRequests = new ArrayList(); for (JAXBElement req : requests) { try { - stalRequests.add(translator.translate(req)); + stalRequests.add(stalTranslator.translate(req)); } catch (TranslationException ex) { log.error("Received unknown request from server STAL: " + ex.getMessage()); throw new RuntimeException(ex); @@ -123,7 +111,7 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { List stalResponses = handleRequest(stalRequests); for (STALResponse stalResponse : stalResponses) { try { - responses.add(translator.translate(stalResponse)); + responses.add(stalTranslator.translate(stalResponse)); } catch (TranslationException ex) { log.error("Received unknown response from STAL: " + ex.getMessage()); throw new RuntimeException(ex); @@ -184,7 +172,7 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { } } - sendRedirect(); + applet.sendRedirect(sessionId); } /** @@ -218,38 +206,4 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { log.error(e); } } - - protected void sendRedirect() { - try { - URL redirectURL = params.getURLParameter(BKUApplet.REDIRECT_URL, - sessionId); - String redirectTarget = params.getAppletParameter(BKUApplet.REDIRECT_TARGET); - if (redirectTarget == null) { - log.info("Done. Redirecting to " + redirectURL + " ..."); - ctx.showDocument(redirectURL); - } else { - log.info("Done. Redirecting to " + redirectURL + " (target=" + redirectTarget + ") ..."); - ctx.showDocument(redirectURL, redirectTarget); - } - } catch (MalformedURLException ex) { - log.warn("Failed to redirect: " + ex.getMessage(), ex); - // gui.showErrorDialog(errorMsg, okListener, actionCommand) - } - } - - private STALPortType getSTALPort() throws MalformedURLException { - URL wsdlURL = params.getURLParameter(BKUApplet.WSDL_URL); - log.debug("STAL WSDL at " + wsdlURL); - QName endpointName = new QName(BKUApplet.STAL_WSDL_NS, - BKUApplet.STAL_SERVICE); - STALService stal = new STALService(wsdlURL, endpointName); - return stal.getSTALPort(); - } - - private void registerSignRequestHandler(STALPortType stalPort, String sessionId) { - log.debug("register SignRequestHandler (resolve hashdata via STAL Webservice)"); - AppletHashDataDisplay handler = new AppletHashDataDisplay(stalPort, - sessionId); - addRequestHandler(SignRequest.class, handler); - } } diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletParameterProvider.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletParameterProvider.java deleted file mode 100644 index 42e2d6ff..00000000 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletParameterProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * 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 at.gv.egiz.bku.online.applet; - -import java.net.MalformedURLException; -import java.net.URL; - -/** - * - * @author Clemens Orthacker - */ -public interface AppletParameterProvider { - - /** - * Applet configuration parameters - * - * @param paramKey - * @return null if no parameter is provided for the given key - */ - String getAppletParameter(String paramKey); - - /** - * Get applet configuration parameter as (absolute) URL - * - * @param paramKey - * @return a URL - * @throws MalformedURLException if configured URL is invalid - * or no parameter is provided for the given key - */ - URL getURLParameter(String paramKey) throws MalformedURLException; - - /** - * Get applet configuration parameter as (absolute) URL - * - * @param paramKey - * @param sessionId adds the jsessionid to the URL - * @return a URL - * @throws MalformedURLException if configured URL is invalid - * or no parameter is provided for the given key - */ - URL getURLParameter(String paramKey, String sessionId) throws MalformedURLException; -} diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java index 5e60ed3e..d4b2018d 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java @@ -16,8 +16,10 @@ */ package at.gv.egiz.bku.online.applet; +import at.gv.egiz.bku.gui.BKUGUIFacade.Style; import at.gv.egiz.bku.gui.DefaultHelpListener; import at.gv.egiz.bku.gui.AbstractHelpListener; +import at.gv.egiz.stal.service.translator.STALTranslator; import java.net.MalformedURLException; import java.net.URL; import java.util.Locale; @@ -30,15 +32,18 @@ import org.apache.commons.logging.LogFactory; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.BKUGUIFactory; +import at.gv.egiz.stal.service.STALPortType; +import at.gv.egiz.stal.service.STALService; +import java.awt.Container; +import javax.xml.namespace.QName; /** * Note: all swing code is executed by the event dispatch thread (see * BKUGUIFacade) */ -public class BKUApplet extends JApplet implements AppletParameterProvider { +public class BKUApplet extends JApplet { private static Log log = LogFactory.getLog(BKUApplet.class); - /** * Applet parameter keys */ @@ -55,18 +60,15 @@ public class BKUApplet extends JApplet implements AppletParameterProvider { // public static final String HASHDATA_DISPLAY_INTERNAL = "internal"; // public static final String HASHDATA_DISPLAY_BROWSER = "browser"; public static final String HASHDATA_DISPLAY_FRAME = "frame"; - /** * STAL WSDL namespace and service name */ public static final String STAL_WSDL_NS = "http://www.egiz.gv.at/wsdl/stal"; public static final String STAL_SERVICE = "STALService"; - /** * Dummy session id, used if no sessionId parameter is provided */ protected static final String TEST_SESSION_ID = "TestSession"; - /** * STAL */ @@ -81,17 +83,17 @@ public class BKUApplet extends JApplet implements AppletParameterProvider { public void init() { log.info("Welcome to MOCCA"); log.debug("Called init()"); - + HttpsURLConnection.setDefaultSSLSocketFactory(InternalSSLSocketFactory.getInstance()); - String locale = getAppletParameter(LOCALE); + String locale = getParameter(LOCALE); if (locale != null) { this.setLocale(new Locale(locale)); } - log.debug("setting locale to " + getLocale()); + log.debug("setting locale: " + getLocale()); BKUGUIFacade.Style guiStyle; - String guiStyleParam = getAppletParameter(GUI_STYLE); + String guiStyleParam = getParameter(GUI_STYLE); if ("advanced".equals(guiStyleParam)) { guiStyle = BKUGUIFacade.Style.advanced; } else if ("tiny".equals(guiStyleParam)) { @@ -99,30 +101,33 @@ public class BKUApplet extends JApplet implements AppletParameterProvider { } else { guiStyle = BKUGUIFacade.Style.simple; } - + log.debug("setting gui-style: " + guiStyle); + URL backgroundImgURL = null; try { - backgroundImgURL = getURLParameter(BACKGROUND_IMG); + backgroundImgURL = getURLParameter(BACKGROUND_IMG, null); + log.debug("setting background: " + backgroundImgURL); } catch (MalformedURLException ex) { log.warn("failed to load applet background image: " + ex.getMessage() + ", using default"); } - + AbstractHelpListener helpListener = null; try { - URL helpURL = getURLParameter(HELP_URL); -// helpListener = new BrowserHelpListener(getAppletContext(), helpURL, getLocale()); - helpListener = new DefaultHelpListener(getAppletContext(), helpURL, getLocale()); + helpListener = new DefaultHelpListener(getAppletContext(), + getURLParameter(HELP_URL, null), getLocale()); + if (log.isDebugEnabled()) { + log.debug("setting helpURL: " + getURLParameter(HELP_URL, null)); + } } catch (MalformedURLException ex) { log.warn("failed to load help URL: " + ex.getMessage() + ", disabling help"); } - - BKUGUIFacade gui = BKUGUIFactory.createGUI(getContentPane(), - getLocale(), - guiStyle, - backgroundImgURL, + + BKUGUIFacade gui = createGUI(getContentPane(), getLocale(), + guiStyle, + backgroundImgURL, helpListener); - worker = new AppletBKUWorker(gui, getAppletContext(), this); + worker = new AppletBKUWorker(this, gui); } @Override @@ -145,15 +150,7 @@ public class BKUApplet extends JApplet implements AppletParameterProvider { log.debug("Called destroy()"); } - @Override - public String getAppletParameter(String paramKey) { - String param = getParameter(paramKey); - log.info("applet parameter: " + paramKey + ": " + param); - return param; - } - - @Override - public URL getURLParameter(String paramKey, String sessionId) throws MalformedURLException { + protected URL getURLParameter(String paramKey, String sessionId) throws MalformedURLException { String urlParam = getParameter(paramKey); if (urlParam != null) { URL codebase = getCodeBase(); @@ -173,15 +170,54 @@ public class BKUApplet extends JApplet implements AppletParameterProvider { } catch (MalformedURLException ex) { log.error("applet paremeter " + urlParam + " is not a valid URL: " + ex.getMessage()); throw ex; - } + } } else { log.error("applet paremeter " + urlParam + " not set"); throw new MalformedURLException(urlParam + " not set"); } } - - @Override - public URL getURLParameter(String paramKey) throws MalformedURLException { - return getURLParameter(paramKey, null); + + /** + * provides a means to for subclasses to inject a different GUI + */ + protected BKUGUIFacade createGUI(Container contentPane, + Locale locale, + Style guiStyle, + URL backgroundImgURL, + AbstractHelpListener helpListener) { + return BKUGUIFactory.createGUI(contentPane, + locale, + guiStyle, + backgroundImgURL, + helpListener); + } + + protected STALPortType getSTALPort() throws MalformedURLException { + URL wsdlURL = getURLParameter(WSDL_URL, null); + log.debug("setting STAL WSDL: " + wsdlURL); + QName endpointName = new QName(STAL_WSDL_NS, STAL_SERVICE); + STALService stal = new STALService(wsdlURL, endpointName); + return stal.getSTALPort(); + } + + protected STALTranslator getSTALTranslator() { + return new STALTranslator(); + } + + protected void sendRedirect(String sessionId) { + try { + URL redirectURL = getURLParameter(REDIRECT_URL, sessionId); + String redirectTarget = getParameter(REDIRECT_TARGET); + if (redirectTarget == null) { + log.info("Done. Redirecting to " + redirectURL + " ..."); + getAppletContext().showDocument(redirectURL); + } else { + log.info("Done. Redirecting to " + redirectURL + " (target=" + redirectTarget + ") ..."); + getAppletContext().showDocument(redirectURL, redirectTarget); + } + } catch (MalformedURLException ex) { + log.warn("Failed to redirect: " + ex.getMessage(), ex); + // gui.showErrorDialog(errorMsg, okListener, actionCommand) + } } } diff --git a/BKUApplet/src/test/resources/appletTest.html b/BKUApplet/src/test/resources/appletTest.html index c8bd99d3..4a768f91 100644 --- a/BKUApplet/src/test/resources/appletTest.html +++ b/BKUApplet/src/test/resources/appletTest.html @@ -18,7 +18,7 @@
diff --git a/BKULocal/pom.xml b/BKULocal/pom.xml index 0f5757b8..5fd142a2 100644 --- a/BKULocal/pom.xml +++ b/BKULocal/pom.xml @@ -9,7 +9,7 @@ BKULocal war BKU Local - 1.0.4-SNAPSHOT + 1.0.2-SNAPSHOT scm:svn:svn://svn.egovlabs.gv.at/svnroot/mocca/trunk/BKULocal diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java index 91d0aba0..61cc7c4c 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java @@ -22,7 +22,6 @@ import at.gv.egiz.stal.QuitRequest; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; -import at.gv.egiz.stal.ext.APDUScriptRequest; import java.util.List; import javax.swing.JDialog; diff --git a/BKULocalApp/pom.xml b/BKULocalApp/pom.xml index 52bc4e36..79a270d8 100644 --- a/BKULocalApp/pom.xml +++ b/BKULocalApp/pom.xml @@ -5,10 +5,10 @@ 1.0.5-SNAPSHOT 4.0.0 - at.gv.egiz.bku + at.gv.egiz BKULocalApp BKU Local App - 1.0.4-SNAPSHOT + 1.0.2-SNAPSHOT @@ -76,7 +76,7 @@ at.gv.egiz BKULocal - 1.0.4-SNAPSHOT + 1.0.2-SNAPSHOT war diff --git a/BKUOnline/pom.xml b/BKUOnline/pom.xml index c82cfc1e..fc5f04fa 100644 --- a/BKUOnline/pom.xml +++ b/BKUOnline/pom.xml @@ -1,4 +1,4 @@ - + bku @@ -56,25 +56,20 @@ 1.0.5-SNAPSHOT compile - - - at.gv.egiz - BKUApplet - 1.0.5-SNAPSHOT - provided - - + at.gv.egiz STALService 1.0.5-SNAPSHOT - at.gv.egiz STALXService 1.0.2-SNAPSHOT - + @@ -102,10 +97,30 @@ com.sun.xml.stream 1.0.1 + + + at.gv.egiz + BKUApplet + 1.0.5-SNAPSHOT + provided + + + at.gv.egiz + BKUAppletExt + 1.0.2-SNAPSHOT + provided + + + iaik + iaik_jce_me4se + provided + + - - Tomcat60 - scm:svn:svn://svn.egovlabs.gv.at/svnroot/mocca/trunk/BKUOnline scm:svn:svn://svn.egovlabs.gv.at/svnroot/mocca/trunk/BKUOnline @@ -117,75 +132,31 @@ maven-dependency-plugin - copyapplet-dependencies + copy_applet copy-dependencies ${project.build.directory}/${project.build.finalName}/applet - - at.gv.egiz - BKUApplet - true + at.gv.egiz,commons-logging,iaik + BKUApplet,BKUAppletExt,commons-logging,iaik_jce_me4se true - - - - copyapplet - - copy - - - ${project.build.directory}/${project.build.finalName}/applet - - - commons-logging - commons-logging - - - iaik - iaik_jce_me4se - - + true - + maven-war-plugin 2.0.2 - - true - + true - - ${project.version}-r${buildNumber} - + ${project.version}-r${buildNumber} @@ -211,7 +182,7 @@ - jaxb-generate + jaxb-generate-stal @@ -245,4 +216,7 @@ - \ No newline at end of file + + Tomcat60 + + diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java index d9be0981..c758bcee 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/BKURequestHandler.java @@ -133,6 +133,9 @@ public class BKURequestHandler extends SpringBKUServlet { .getFormData("appletHashDataDisplay"), charset); String localeFormParam = getStringFromStream(bindingProcessor .getFormData("locale"), charset); + String extension = getStringFromStream(bindingProcessor + .getFormData("appletExtension"), charset); + if (width != null) { try { log.trace("Found applet width parameter: " + width); diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java index a617c61f..81b70b7c 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java @@ -19,19 +19,17 @@ package at.gv.egiz.stal.service.impl; import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.HashDataInput; -import at.gv.egiz.stal.InfoboxReadRequest; import at.gv.egiz.stal.QuitRequest; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; import at.gv.egiz.stal.service.translator.STALTranslator; import at.gv.egiz.stal.service.translator.TranslationException; -import at.gv.egiz.stal.service.types.InfoboxReadRequestType; import at.gv.egiz.stal.service.types.ObjectFactory; import at.gv.egiz.stal.service.types.QuitRequestType; import at.gv.egiz.stal.service.types.RequestType; import at.gv.egiz.stal.service.types.ResponseType; -import at.gv.egiz.stal.service.types.SignRequestType; +import at.gv.egiz.stalx.service.translator.STALXTranslationHandler; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -71,10 +69,12 @@ public class STALRequestBrokerImpl implements STALRequestBroker { if (timeoutMillisec <= 0) timeoutMillisec = DEFAULT_TIMEOUT_MS; timeout = timeoutMillisec; -// translator.registerTranslationHandler(handler); requests = new ArrayList>(); responses = new ArrayList>(); hashDataInputs = new ArrayList(); + + // register handler for STAL-X + translator.registerTranslationHandler(new STALXTranslationHandler()); } /** diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java index afeba9cb..a30c6bb2 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java @@ -18,6 +18,8 @@ package at.gv.egiz.stal.service.impl; //import at.buergerkarte.namespaces.cardchannel.service.CommandAPDUType; //import at.buergerkarte.namespaces.cardchannel.service.ScriptType; +import at.buergerkarte.namespaces.cardchannel.service.CommandAPDUType; +import at.buergerkarte.namespaces.cardchannel.service.ScriptType; import at.gv.egiz.bku.binding.BindingProcessor; import at.gv.egiz.bku.binding.BindingProcessorManager; import at.gv.egiz.bku.binding.Id; @@ -78,8 +80,10 @@ public class STALServiceImpl implements STALPortType { @Resource protected WebServiceContext wsContext; protected IdFactory idF = IdFactory.getInstance(); + /** JAXB ObjectFactories */ private at.gv.egiz.stal.service.types.ObjectFactory stalObjFactory = new at.gv.egiz.stal.service.types.ObjectFactory(); -// private at.buergerkarte.namespaces.cardchannel.service.ObjectFactory ccObjFactory = new at.buergerkarte.namespaces.cardchannel.service.ObjectFactory(); + /** don't confuse with at.buergerkarte.namespaces.cardchannel */ + private at.buergerkarte.namespaces.cardchannel.service.ObjectFactory ccObjFactory = new at.buergerkarte.namespaces.cardchannel.service.ObjectFactory(); @Override public GetNextRequestResponseType connect(String sessId) { @@ -331,12 +335,12 @@ public class STALServiceImpl implements STALPortType { if (responsesIn == null) { log.info("[TestSession] received CONNECT, return dummy requests "); -// ScriptType scriptT = ccObjFactory.createScriptType(); -// CommandAPDUType cmd = ccObjFactory.createCommandAPDUType(); -// cmd.setValue("TestSession CardChannelCMD 1234".getBytes()); -// scriptT.getResetOrCommandAPDUOrVerifyAPDU().add(cmd); -// reqs.add(ccObjFactory.createScript(scriptT)); - addDummyRequests(reqs); +// addDummyRequests(reqs); + ScriptType scriptT = ccObjFactory.createScriptType(); + CommandAPDUType cmd = ccObjFactory.createCommandAPDUType(); + cmd.setValue("TestSession CardChannelCMD 1234".getBytes()); + scriptT.getResetOrCommandAPDUOrVerifyAPDU().add(cmd); + reqs.add(ccObjFactory.createScript(scriptT)); } else if (responsesIn != null && responsesIn.size() > 0 && responsesIn.get(0).getValue() instanceof ErrorResponseType) { log.info("[TestSession] received ErrorResponse, return QUIT request"); QuitRequestType quitT = stalObjFactory.createQuitRequestType(); diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java index 92559254..9caf950f 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALXJAXBContextFactory.java @@ -47,11 +47,11 @@ public class STALXJAXBContextFactory implements JAXBContextFactory { } List classes = new ArrayList(); classes.addAll(classesToBind); -// Class ccOF = at.buergerkarte.namespaces.cardchannel.service.ObjectFactory.class; -// if (!classes.contains(ccOF)) { -// log.debug("adding " + ccOF + " to JAXBContext seed"); -// classes.add(ccOF); -// } + Class ccOF = at.buergerkarte.namespaces.cardchannel.service.ObjectFactory.class; + if (!classes.contains(ccOF)) { + log.debug("adding " + ccOF + " to JAXBContext seed"); + classes.add(ccOF); + } //TODO add typeReference? diff --git a/BKUOnline/src/main/webapp/applet.jsp b/BKUOnline/src/main/webapp/applet.jsp index 3bf0ff40..ada48f22 100644 --- a/BKUOnline/src/main/webapp/applet.jsp +++ b/BKUOnline/src/main/webapp/applet.jsp @@ -39,6 +39,16 @@ String backgroundImg = (String) session.getAttribute("appletBackground"); String guiStyle = (String) session.getAttribute("appletGuiStyle"); String locale = (String) session.getAttribute("locale"); + + String appletClass, appletArchive; + //if (Boolean.parseBoolean((String) session.getAttribute("appletExtension"))) { + if ("activation".equals(guiStyle)) { + appletArchive = "BKUAppletExt.jar"; + appletClass = "at.gv.egiz.bku.online.applet.ext.BKUAppletExt.class"; + } else { + appletArchive = "BKUApplet.jar"; + appletClass = "at.gv.egiz.bku.online.applet.BKUApplet.class"; + } %> + + + + + + + <% + String locale = request.getParameter("locale"); + if (locale == null) { + String acceptLanguage = request.getHeader("Accept-Language"); + locale = AcceptLanguage.getLocale(acceptLanguage).toString(); + } + String widthP = request.getParameter("appletWidth"); + String heightP = request.getParameter("appletHeight"); + int width = (widthP == null) ? 295 + : Integer.parseInt(widthP); + int height = (heightP == null) ? 195 + : Integer.parseInt(heightP); + String guiStyle = request.getParameter("appletGuiStyle"); + if (guiStyle == null) { + guiStyle = "advanced"; + } + String backgroundImg = request.getParameter("appletBackground"); + %> + + + + diff --git a/BKUOnline/src/main/webapp/SLRequestForm.html b/BKUOnline/src/main/webapp/SLRequestForm.html new file mode 100644 index 00000000..2aed5298 --- /dev/null +++ b/BKUOnline/src/main/webapp/SLRequestForm.html @@ -0,0 +1,155 @@ + + + + + Security-Layer v1.2 Request Formular + + + + + + +

Security-Layer v1.2 Request Formular

+ + +

+

+ +
Enter XML Request +

+ + + +

+ + tiny + simple + advanced +

+

+

+

+ + +

+ + Activation + PIN Management +

+ + +
+
+
+ + + diff --git a/BKUOnline/src/main/webapp/css/applet.css b/BKUOnline/src/main/webapp/css/applet.css index 4bfbd77d..d2c734a1 100644 --- a/BKUOnline/src/main/webapp/css/applet.css +++ b/BKUOnline/src/main/webapp/css/applet.css @@ -1,4 +1,3 @@ - root { display: block; } diff --git a/BKUOnline/src/main/webapp/css/main.css b/BKUOnline/src/main/webapp/css/main.css new file mode 100644 index 00000000..114b8da9 --- /dev/null +++ b/BKUOnline/src/main/webapp/css/main.css @@ -0,0 +1,48 @@ +/* +Document : main +Created on : 27.02.2009, 10:24:41 +Author : clemens +Description: +Purpose of the stylesheet follows. +*/ + +/* +TODO customize this sample style +Syntax recommendation http://www.w3.org/TR/REC-CSS2/ +*/ + +root { + display: block; +} + +body { + font-family: sans-serif; + font-size: 14px; +} + +h1 { + font-size: 16px; +} + +.box { + margin-top: 10px; + color: #292929; + width: 250px; + border: 1px solid #BABABA; + background-color: #ddd; + padding-left: 10px; + padding-right: 10px; + margin-left: 10px; + margin-bottom: 1em; + -o-border-radius: 10px; + -moz-border-radius: 12px; + -webkit-border-radius: 10px; + -webkit-box-shadow: 0px 3px 7px #adadad; + border-radius: 10px; + -moz-box-sizing: border-box; + -opera-sizing: border-box; + -webkit-box-sizing: border-box; + -khtml-box-sizing: border-box; + box-sizing: border-box; + overflow: hidden; +} \ No newline at end of file diff --git a/BKUOnline/src/main/webapp/index.html b/BKUOnline/src/main/webapp/index.html index 94e2890f..653da5b1 100644 --- a/BKUOnline/src/main/webapp/index.html +++ b/BKUOnline/src/main/webapp/index.html @@ -16,44 +16,21 @@ --> - -BKU Online - - - - -
-

-

TestRequest

-Security Layer Request -

STAL Service

-STAL Service Endpoint Information -

-
- - - + + BKU Online + + + + +
+

+

SL Request

+ Security Layer Request +

PIN Management

+ PIN Management Applet +

STAL Service

+ STAL Service Endpoint +

+
+ diff --git a/BKUOnline/src/main/webapp/slRequestForm.html b/BKUOnline/src/main/webapp/slRequestForm.html deleted file mode 100644 index 76cd1be9..00000000 --- a/BKUOnline/src/main/webapp/slRequestForm.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - Security-Layer v1.2 Request Formular - - - - - -

Security-Layer v1.2 Request Formular

- - -

-

- -
Enter XML Request -

- - - -

- - tiny - simple - advanced -

-

-

-

- - -

- - Activation - PIN Management -

- - -
-
-
- - - diff --git a/STAL/src/main/java/at/gv/egiz/stal/STAL.java b/STAL/src/main/java/at/gv/egiz/stal/STAL.java index 7015ec29..a88d8f89 100644 --- a/STAL/src/main/java/at/gv/egiz/stal/STAL.java +++ b/STAL/src/main/java/at/gv/egiz/stal/STAL.java @@ -39,5 +39,5 @@ public interface STAL { * If the locale is not set the default locale will be used. * @param locale must not be null. */ - public void setLocale(Locale locale); +// public void setLocale(Locale locale); } \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManagerImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManagerImpl.java index 5b061850..144416ed 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManagerImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/BindingProcessorManagerImpl.java @@ -216,7 +216,7 @@ public class BindingProcessorManagerImpl implements BindingProcessorManager { bindingProcessor.init(stal, commandInvokerClass.newInstance()); if (locale != null) { bindingProcessor.setLocale(locale); - stal.setLocale(locale); +// stal.setLocale(locale); } return bindingProcessor; } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java index b6c5a8ca..23b71690 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java @@ -54,7 +54,7 @@ public abstract class AbstractBKUWorker extends AbstractSMCCSTAL implements Acti throw new NullPointerException("No BKU GUI provided"); } this.gui = gui; - this.locale = gui.getLocale(); +// this.locale = gui.getLocale(); addRequestHandler(QuitRequest.class, this); } @@ -149,7 +149,7 @@ public abstract class AbstractBKUWorker extends AbstractSMCCSTAL implements Acti } break; case SMCCHelper.CARD_FOUND: - signatureCard = smccHelper.getSignatureCard(locale); + signatureCard = smccHelper.getSignatureCard(gui.getLocale()); return false; } smccHelper.update(3000); diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 0074860f..3691156e 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -20,7 +20,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Locale; +//import java.util.Locale; import java.util.Map; import java.util.Set; @@ -41,7 +41,7 @@ public abstract class AbstractSMCCSTAL implements STAL { public final static int DEFAULT_MAX_RETRIES = 1; - protected Locale locale = Locale.getDefault(); +// protected Locale locale = Locale.getDefault(); protected SignatureCard signatureCard = null; protected Map handlerMap = new HashMap(); @@ -159,13 +159,13 @@ public abstract class AbstractSMCCSTAL implements STAL { return handlerMap.get(request.getSimpleName()); } - @Override - public void setLocale(Locale locale) { - if (locale == null) { - throw new NullPointerException("Locale must not be set to null"); - } - this.locale = locale; - } +// @Override +// public void setLocale(Locale locale) { +// if (locale == null) { +// throw new NullPointerException("Locale must not be set to null"); +// } +// this.locale = locale; +// } public void setMaxRetries(int maxRetries) { this.maxRetries = maxRetries; -- cgit v1.2.3 From e177419331b8849497d25d3eb1866c5dc715bc88 Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 6 Mar 2009 14:53:37 +0000 Subject: 1.1-rc4 git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@312 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../java/at/gv/egiz/bku/gui/PINManagementGUI.java | 229 +++++++++------ .../at/gv/egiz/bku/gui/PINManagementGUIFacade.java | 13 +- .../at/gv/egiz/bku/gui/PINStatusTableModel.java | 6 +- .../bku/smccstal/ext/GetPINStatusException.java | 41 +++ .../smccstal/ext/PINManagementRequestHandler.java | 312 ++++++++++++++++----- .../gv/egiz/bku/gui/ActivationMessages.properties | 7 + .../egiz/bku/gui/ActivationMessages_en.properties | 4 + .../at/gv/egiz/bku/local/stal/BKUGuiProxy.java | 6 + .../src/test/resources/commons-logging.properties | 16 ++ BKUOnline/src/test/resources/log4j.properties | 29 ++ smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 82 +++++- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 57 ++-- .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 96 ++++++- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 13 +- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 13 +- .../java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java | 16 +- .../java/at/gv/egiz/marshal/NamespacePrefix.java | 2 +- 17 files changed, 703 insertions(+), 239 deletions(-) create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/GetPINStatusException.java create mode 100644 BKUOnline/src/test/resources/commons-logging.properties create mode 100644 BKUOnline/src/test/resources/log4j.properties (limited to 'smccSTAL/src') diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java index 1276f2d0..c904be0c 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -20,6 +20,7 @@ package at.gv.egiz.bku.gui; import at.gv.egiz.smcc.PINSpec; import java.awt.Container; import java.awt.Cursor; +import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; @@ -55,6 +56,8 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac /** remember the pinSpec to return to worker */ protected PINSpec pinSpec; + protected enum DIALOG { VERIFY, ACTIVATE, CHANGE, UNBLOCK }; + public PINManagementGUI(Container contentPane, Locale locale, Style guiStyle, @@ -84,6 +87,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac final String activateCmd, final String changeCmd, final String unblockCmd, + final String verifyCmd, final ActionListener cancelListener, final String cancelCmd) { @@ -161,9 +165,10 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac activateButton.setText(getMessage(BUTTON_CHANGE)); activateButton.setEnabled(true); activateButton.setActionCommand(changeCmd); - } else { - activateButton.setText(getMessage(BUTTON_ACTIVATE)); - activateButton.setEnabled(false); + } else if (status == STATUS.UNKNOWN) { + activateButton.setText(getMessage(BUTTON_VERIFY)); + activateButton.setEnabled(true); + activateButton.setActionCommand(verifyCmd); } } } @@ -234,11 +239,11 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac final ActionListener okListener, final String okCommand, final ActionListener cancelListener, final String cancelCommand) { log.debug("scheduling activate pin dialog"); - showPINDialog(false, pin, okListener, okCommand, cancelListener, cancelCommand); + showPINDialog(DIALOG.ACTIVATE, pin, okListener, okCommand, cancelListener, cancelCommand); } - private void showPINDialog(final boolean changePin, final PINSpec pinSpec, + private void showPINDialog(final DIALOG type, final PINSpec pinSpec, final ActionListener okListener, final String okCommand, final ActionListener cancelListener, final String cancelCommand) { @@ -248,17 +253,25 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac public void run() { String HELP_TOPIC, TITLE, MESSAGE_MGMT; - if (changePin) { + HELP_TOPIC = HELP_PINMGMT; + + if (type == DIALOG.CHANGE) { log.debug("show change pin dialog"); - HELP_TOPIC = HELP_PINMGMT; TITLE = TITLE_CHANGE_PIN; MESSAGE_MGMT = MESSAGE_CHANGE_PIN; - } else { + } else if (type == DIALOG.ACTIVATE) { log.debug("show activate pin dialog"); - HELP_TOPIC = HELP_PINMGMT; TITLE = TITLE_ACTIVATE_PIN; MESSAGE_MGMT = MESSAGE_ACTIVATE_PIN; oldPinField = null; + } else if (type == DIALOG.VERIFY) { + log.debug("show verify pin dialog"); + TITLE = TITLE_VERIFY_PIN; + MESSAGE_MGMT = MESSAGE_VERIFY_PIN; + } else { + log.debug("show unblock pin dialog"); + TITLE = TITLE_UNBLOCK_PIN; + MESSAGE_MGMT = MESSAGE_UNBLOCK_PIN; } mainPanel.removeAll(); @@ -267,7 +280,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac helpListener.setHelpTopic(HELP_TOPIC); JLabel mgmtLabel = new JLabel(); - mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); if (renderHeaderPanel) { titleLabel.setText(getMessage(TITLE)); @@ -282,73 +295,83 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac } JButton okButton = new JButton(); - okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~Font.BOLD)); okButton.setText(getMessage(BUTTON_OK)); - okButton.setEnabled(false); + okButton.setEnabled(type == DIALOG.VERIFY && pinSpec.getMinLength() == 0); okButton.setActionCommand(okCommand); okButton.addActionListener(okListener); + JLabel oldPinLabel = null; + JLabel repeatPinLabel = null; JLabel pinLabel = new JLabel(); - pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - String pinLabelPattern = (changePin) ? getMessage(LABEL_NEW_PIN) : getMessage(LABEL_PIN); + pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~Font.BOLD)); + String pinLabelPattern = (type == DIALOG.CHANGE) ? getMessage(LABEL_NEW_PIN) : getMessage(LABEL_PIN); pinLabel.setText(MessageFormat.format(pinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); final JPasswordField repeatPinField = new JPasswordField(); pinField = new JPasswordField(); pinField.setText(""); - pinField.setDocument(new PINDocument(pinSpec, null)); pinField.setActionCommand(okCommand); pinField.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (pinField.getPassword().length >= pinSpec.getMinLength()) { - repeatPinField.requestFocusInWindow(); - } - } - }); - JLabel repeatPinLabel = new JLabel(); - repeatPinLabel.setFont(pinLabel.getFont()); - String repeatPinLabelPattern = getMessage(LABEL_REPEAT_PIN); - repeatPinLabel.setText(MessageFormat.format(repeatPinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); - - repeatPinField.setText(""); - repeatPinField.setDocument(new PINDocument(pinSpec, okButton, pinField.getDocument())); - repeatPinField.setActionCommand(okCommand); - repeatPinField.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - if (pinField.getPassword().length >= pinSpec.getMinLength()) { + if (type == DIALOG.VERIFY) { okListener.actionPerformed(e); + } else { + repeatPinField.requestFocusInWindow(); + } } } }); - JLabel oldPinLabel = null; - if (changePin) { - oldPinLabel = new JLabel(); - oldPinLabel.setFont(oldPinLabel.getFont().deriveFont(oldPinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - String oldPinLabelPattern = getMessage(LABEL_OLD_PIN); - oldPinLabel.setText(MessageFormat.format(oldPinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); - - oldPinField = new JPasswordField(); - oldPinField.setText(""); - oldPinField.setDocument(new PINDocument(pinSpec, null)); - oldPinField.setActionCommand(okCommand); - oldPinField.addActionListener(new ActionListener() { + if (type != DIALOG.VERIFY) { + pinField.setDocument(new PINDocument(pinSpec, null)); + repeatPinLabel = new JLabel(); + repeatPinLabel.setFont(pinLabel.getFont()); + String repeatPinLabelPattern = getMessage(LABEL_REPEAT_PIN); + repeatPinLabel.setText(MessageFormat.format(repeatPinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); + + repeatPinField.setText(""); + repeatPinField.setDocument(new PINDocument(pinSpec, okButton, pinField.getDocument())); + repeatPinField.setActionCommand(okCommand); + repeatPinField.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (oldPinField.getPassword().length >= pinSpec.getMinLength()) { - pinField.requestFocusInWindow(); + if (pinField.getPassword().length >= pinSpec.getMinLength()) { + okListener.actionPerformed(e); } } }); + + if (type == DIALOG.CHANGE) { + oldPinLabel = new JLabel(); + oldPinLabel.setFont(oldPinLabel.getFont().deriveFont(oldPinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + String oldPinLabelPattern = getMessage(LABEL_OLD_PIN); + oldPinLabel.setText(MessageFormat.format(oldPinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); + + oldPinField = new JPasswordField(); + oldPinField.setText(""); + oldPinField.setDocument(new PINDocument(pinSpec, null)); + oldPinField.setActionCommand(okCommand); + oldPinField.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (oldPinField.getPassword().length >= pinSpec.getMinLength()) { + pinField.requestFocusInWindow(); + } + } + }); + } // else -> ACTIVATE (not verify, not change) + } else { + pinField.setDocument(new PINDocument(pinSpec, okButton)); } - + JLabel pinsizeLabel = new JLabel(); - pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, pinsizeLabel.getFont().getSize()-2)); + pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~Font.BOLD, pinsizeLabel.getFont().getSize()-2)); String pinsizePattern = getMessage(LABEL_PINSIZE); String pinSize = String.valueOf(pinSpec.getMinLength()); if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { @@ -375,37 +398,39 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac GroupLayout.ParallelGroup pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup(); - if (pinLabelPos == PinLabelPosition.ABOVE) { - if (changePin) { - pinHorizontal - .addComponent(oldPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); - pinVertical - .addComponent(oldPinLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); - } - pinHorizontal - .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(mainPanelLayout.createSequentialGroup() - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); - pinVertical - .addComponent(pinLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(repeatPinLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinsizeLabel); - } else { - if (changePin) { +// if (pinLabelPos == PinLabelPosition.ABOVE) { +// if (changePin) { +// pinHorizontal +// .addComponent(oldPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +// .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); +// pinVertical +// .addComponent(oldPinLabel) +// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +// .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); +// } +// pinHorizontal +// .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +// .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +// .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +// .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +// .addGroup(mainPanelLayout.createSequentialGroup() +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); +// pinVertical +// .addComponent(pinLabel) +// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +// .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +// .addComponent(repeatPinLabel) +// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +// .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +// .addComponent(pinsizeLabel); +// } else { + + + if (type == DIALOG.CHANGE) { pinHorizontal .addGroup(mainPanelLayout.createSequentialGroup() .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) @@ -422,8 +447,16 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(oldPinLabel) .addComponent(oldPinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(pinLabel) + .addComponent(pinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(repeatPinLabel) + .addComponent(repeatPinField)) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); - } else { + } else if (type == DIALOG.ACTIVATE) { pinHorizontal .addGroup(mainPanelLayout.createSequentialGroup() .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) @@ -434,12 +467,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); - } - pinHorizontal - .addGroup(mainPanelLayout.createSequentialGroup() - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); - pinVertical + pinVertical .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(pinLabel) .addComponent(pinField)) @@ -447,9 +475,27 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(repeatPinLabel) .addComponent(repeatPinField)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); + } else { // VERIFY + pinHorizontal + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); + + pinVertical + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(pinLabel) + .addComponent(pinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); + } + pinHorizontal + .addGroup(mainPanelLayout.createSequentialGroup() + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); + pinVertical .addComponent(pinsizeLabel); - } +// } mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) @@ -503,7 +549,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac final ActionListener cancelListener, final String cancelCommand) { log.debug("scheduling change pin dialog"); - showPINDialog(true, pin, okListener, okCommand, cancelListener, cancelCommand); + showPINDialog(DIALOG.CHANGE, pin, okListener, okCommand, cancelListener, cancelCommand); } @Override @@ -612,4 +658,9 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac return bs; } + + @Override + public void showVerifyPINDialog(PINSpec pin, ActionListener okListener, String okCmd, ActionListener cancelListener, String cancelCmd) { + showPINDialog(DIALOG.VERIFY, pin, okListener, okCmd, cancelListener, cancelCmd); + } } diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java index 6b083e16..9c630431 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -31,6 +31,7 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String TITLE_PINMGMT = "title.pin.mgmt"; public static final String TITLE_ACTIVATE_PIN = "title.activate.pin"; public static final String TITLE_CHANGE_PIN = "title.change.pin"; + public static final String TITLE_VERIFY_PIN = "title.verify.pin"; public static final String TITLE_UNBLOCK_PIN = "title.unblock.pin"; public static final String TITLE_ACTIVATE_SUCCESS = "title.activate.success"; public static final String TITLE_CHANGE_SUCCESS = "title.change.success"; @@ -39,19 +40,25 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String MESSAGE_PINMGMT = "message.pin.mgmt"; public static final String MESSAGE_ACTIVATE_PIN = "message.activate.pin"; public static final String MESSAGE_CHANGE_PIN = "message.change.pin"; + public static final String MESSAGE_VERIFY_PIN = "message.verify.pin"; public static final String MESSAGE_UNBLOCK_PIN = "message.unblock.pin"; public static final String LABEL_OLD_PIN = "label.old.pin"; public static final String LABEL_NEW_PIN = "label.new.pin"; public static final String LABEL_REPEAT_PIN = "label.repeat.pin"; + public static final String ERR_STATUS = "err.status"; public static final String ERR_ACTIVATE = "err.activate"; public static final String ERR_CHANGE = "err.change"; public static final String ERR_UNBLOCK = "err.unblock"; + public static final String ERR_VERIFY = "err.verify"; public static final String ERR_RETRIES = "err.retries"; + public static final String ERR_LOCKED = "err.locked"; + public static final String ERR_NOT_ACTIVE = "err.not.active"; public static final String BUTTON_ACTIVATE = "button.activate"; public static final String BUTTON_UNBLOCK = "button.unblock"; public static final String BUTTON_CHANGE = "button.change"; + public static final String BUTTON_VERIFY = "button.verify"; public static final String STATUS_ACTIVE = "status.active"; public static final String STATUS_BLOCKED = "status.blocked"; @@ -61,7 +68,7 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED, UNKNOWN }; public void showPINManagementDialog(Map pins, - ActionListener activateListener, String activateCmd, String changeCmd, String unblockCmd, + ActionListener activateListener, String activateCmd, String changeCmd, String unblockCmd, String verifyCmd, ActionListener cancelListener, String cancelCmd); public void showActivatePINDialog(PINSpec pin, @@ -76,6 +83,10 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { ActionListener okListener, String okCmd, ActionListener cancelListener, String cancelCmd); + public void showVerifyPINDialog(PINSpec pin, + ActionListener okListener, String okCmd, + ActionListener cancelListener, String cancelCmd); + public char[] getOldPin(); public PINSpec getSelectedPINSpec(); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java index feaa5072..052c13b2 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java @@ -20,8 +20,6 @@ import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; import at.gv.egiz.smcc.PINSpec; import java.util.Map; import javax.swing.table.DefaultTableModel; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * @@ -29,7 +27,7 @@ import org.apache.commons.logging.LogFactory; */ public class PINStatusTableModel extends DefaultTableModel { - protected static final Log log = LogFactory.getLog(PINStatusTableModel.class); +// protected static final Log log = LogFactory.getLog(PINStatusTableModel.class); protected Class[] types; public PINStatusTableModel(Map pinStatuses) { @@ -37,7 +35,7 @@ public class PINStatusTableModel extends DefaultTableModel { if (pinStatuses == null) { throw new RuntimeException("pinStatuses must not be null"); } - log.trace(pinStatuses.size() + " PINs"); +// log.trace(pinStatuses.size() + " PINs"); types = new Class[] { PINSpec.class, STATUS.class }; for (PINSpec pinSpec : pinStatuses.keySet()) { addRow(new Object[] { pinSpec, pinStatuses.get(pinSpec) }); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/GetPINStatusException.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/GetPINStatusException.java new file mode 100644 index 00000000..abbe66a1 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/GetPINStatusException.java @@ -0,0 +1,41 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal.ext; + +import at.gv.egiz.smcc.SignatureCardException; + +/** + * + * @author Clemens Orthacker + */ +public class GetPINStatusException extends SignatureCardException { + + /** + * Creates a new instance of GetStatusException without detail message. + */ + public GetPINStatusException() { + } + + + /** + * Constructs an instance of GetStatusException with the specified detail message. + * @param msg the detail message. + */ + public GetPINStatusException(String msg) { + super(msg); + } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java index c8472c97..66db0484 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java @@ -20,7 +20,10 @@ import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.PINManagementGUIFacade; import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; import at.gv.egiz.bku.smccstal.AbstractRequestHandler; +import at.gv.egiz.smcc.LockedException; +import at.gv.egiz.smcc.NotActivatedException; import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.STARCOSCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.VerificationFailedException; import at.gv.egiz.smcc.util.SMCCHelper; @@ -32,6 +35,8 @@ import at.gv.egiz.stal.ext.PINManagementResponse; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; @@ -48,13 +53,20 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { protected static final Log log = LogFactory.getLog(PINManagementRequestHandler.class); + Map pinStatuses; + @Override public STALResponse handleRequest(STALRequest request) throws InterruptedException { if (request instanceof PINManagementRequest) { PINManagementGUIFacade gui = (PINManagementGUIFacade) this.gui; - showPINManagementDialog(gui); + try { + pinStatuses = getPINStatuses(); + + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); while (true) { @@ -63,7 +75,9 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { if ("cancel".equals(actionCommand)) { return new PINManagementResponse(); } else if ("back".equals(actionCommand)) { - showPINManagementDialog(gui); + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); } else { PINSpec selectedPIN = gui.getSelectedPINSpec(); @@ -72,63 +86,163 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { } if ("activate_enterpin".equals(actionCommand)) { - gui.showActivatePINDialog(selectedPIN, this, "activate", this, "back"); + gui.showActivatePINDialog(selectedPIN, + this, "activate", this, "back"); } else if ("change_enterpin".equals(actionCommand)) { - gui.showChangePINDialog(selectedPIN, this, "change", this, "back"); + gui.showChangePINDialog(selectedPIN, + this, "change", this, "back"); } else if ("unblock_enterpuk".equals(actionCommand)) { - gui.showUnblockPINDialog(selectedPIN, this, "unblock", this, "back"); + gui.showUnblockPINDialog(selectedPIN, + this, "unblock", this, "back"); + } else if ("verify_enterpin".equals(actionCommand)) { + gui.showVerifyPINDialog(selectedPIN, + this, "verify", this, "back"); } else if ("activate".equals(actionCommand)) { try { - card.activatePIN(selectedPIN.getKID(), - selectedPIN.getContextAID(), + log.debug("activate " + selectedPIN.getLocalizedName()); + card.activatePIN(selectedPIN, String.valueOf(gui.getPin())); + updatePINStatus(selectedPIN, STATUS.ACTIV); gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, new Object[] {selectedPIN.getLocalizedName()}, this, "ok"); waitForAction(); - showPINManagementDialog(gui); + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); + } catch (GetPINStatusException ex) { + log.error("failed to get " + selectedPIN.getLocalizedName() + + " status: " + ex.getMessage()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, + this, "cancel"); } catch (SignatureCardException ex) { - log.error("failed to activate " + selectedPIN.getLocalizedName() + ": " + ex.getMessage()); + log.error("failed to activate " + selectedPIN.getLocalizedName() + + ": " + ex.getMessage()); gui.showErrorDialog(PINManagementGUIFacade.ERR_ACTIVATE, new Object[] {selectedPIN.getLocalizedName()}, this, "cancel"); } } else if ("change".equals(actionCommand)) { + log.info("change " + selectedPIN.getLocalizedName()); try { - card.changePIN(selectedPIN.getKID(), - selectedPIN.getContextAID(), + card.changePIN(selectedPIN, String.valueOf(gui.getOldPin()), String.valueOf(gui.getPin())); + updatePINStatus(selectedPIN, STATUS.ACTIV); gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, new Object[] {selectedPIN.getLocalizedName()}, this, "ok"); waitForAction(); - showPINManagementDialog(gui); + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); + } catch (GetPINStatusException ex) { + log.error("failed to get " + selectedPIN.getLocalizedName() + + " status: " + ex.getMessage()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, + this, "cancel"); + } catch (LockedException ex) { + log.error("failed to change " + selectedPIN.getLocalizedName() + + ": PIN locked"); + updatePINStatus(selectedPIN, STATUS.BLOCKED); + gui.showErrorDialog(PINManagementGUIFacade.ERR_LOCKED, + new Object[] {selectedPIN.getLocalizedName()}, + this, "ok"); + waitForAction(); + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); } catch (VerificationFailedException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + ": " + ex.getMessage()); + log.error("failed to change " + selectedPIN.getLocalizedName() + + ": " + ex.getMessage()); gui.showErrorDialog(PINManagementGUIFacade.ERR_RETRIES, new Object[] {selectedPIN.getLocalizedName(), ex.getRetries()}, - this, "back"); + this, "change_enterpin"); + } catch (NotActivatedException ex) { + log.error("failed to change " + selectedPIN.getLocalizedName() + + ": PIN not active"); + updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); + gui.showErrorDialog(PINManagementGUIFacade.ERR_NOT_ACTIVE, + new Object[] {selectedPIN.getLocalizedName()}, + this, "ok"); + waitForAction(); + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); } catch (SignatureCardException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + ": " + ex.getMessage()); + log.error("failed to change " + selectedPIN.getLocalizedName() + + ": " + ex.getMessage()); gui.showErrorDialog(PINManagementGUIFacade.ERR_CHANGE, new Object[] {selectedPIN.getLocalizedName()}, this, "cancel"); } } else if ("unblock".equals(actionCommand)) { + log.info("unblock " + selectedPIN.getLocalizedName()); log.error("unblock PIN not implemented"); gui.showErrorDialog(PINManagementGUIFacade.ERR_UNBLOCK, null, this, "cancel"); + } else if ("verify".equals(actionCommand)) { + try { + log.info("verify " + selectedPIN.getLocalizedName()); + int retries = card.verifyPIN(selectedPIN, String.valueOf(gui.getPin())); + log.trace(retries + " retries"); + if (retries < 0) { + updatePINStatus(selectedPIN, STATUS.ACTIV); + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); + } else { + log.error("failed to verify " + selectedPIN.getLocalizedName() + + ": " + retries + " retries left"); + gui.showErrorDialog(PINManagementGUIFacade.ERR_RETRIES, + new Object[] {selectedPIN.getLocalizedName(), retries}, + this, "verify_enterpin"); + } + } catch (GetPINStatusException ex) { + log.error("failed to get " + selectedPIN.getLocalizedName() + + " status: " + ex.getMessage()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, + this, "cancel"); + } catch (LockedException ex) { + log.error("failed to verify " + selectedPIN.getLocalizedName() + + ": PIN locked"); + updatePINStatus(selectedPIN, STATUS.BLOCKED); + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); + } catch (NotActivatedException ex) { + log.error("failed to verify " + selectedPIN.getLocalizedName() + + ": PIN not active"); + updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); + } catch (SignatureCardException ex) { + log.error("failed to verify " + selectedPIN.getLocalizedName() + + ": " + ex.getMessage()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, + new Object[] {selectedPIN.getLocalizedName()}, + this, "cancel"); + } + } else { throw new RuntimeException("unsupported action " + actionCommand); } } } + } catch (GetPINStatusException ex) { + log.error("Failed to get PIN statuses: " + ex.getMessage()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, + this, "ok"); + waitForAction(); + return new ErrorResponse(1000); + } } else { log.error("Got unexpected STAL request: " + request); return new ErrorResponse(1000); } + } @Override @@ -136,75 +250,129 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { return true; } - public Map getPINStatuses() throws SignatureCardException { - Card icc = card.getCard(); - try { - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); + private Map getPINStatuses() throws GetPINStatusException { + HashMap pinStatuses = new HashMap(); + List pins = card.getPINSpecs(); - HashMap pinStatuses = new HashMap(); - List pins = card.getPINSpecs(); + if (card instanceof STARCOSCard) { + Card icc = card.getCard(); + try { + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); - for (PINSpec pinSpec : pins) { - byte kid = pinSpec.getKID(); - byte[] contextAID = pinSpec.getContextAID(); - - if (contextAID != null) { - CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); - ResponseAPDU responseAPDU = channel.transmit(selectAPDU); - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + - ": Failed to select AID " + SMCCHelper.toString(contextAID) + - ": " + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); + for (PINSpec pinSpec : pins) { + byte kid = pinSpec.getKID(); + byte[] contextAID = pinSpec.getContextAID(); + + if (contextAID != null) { + CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); + ResponseAPDU responseAPDU = channel.transmit(selectAPDU); + if (responseAPDU.getSW() != 0x9000) { + icc.endExclusive(); + String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new GetPINStatusException(msg); + } } - } - CommandAPDU verifyAPDU = new CommandAPDU(new byte[]{(byte) 0x00, (byte) 0x20, (byte) 00, kid}); - ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); + CommandAPDU verifyAPDU = new CommandAPDU(new byte[] { + (byte) 0x00, (byte) 0x20, (byte) 00, kid }); + ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); - STATUS status = STATUS.UNKNOWN; - if (responseAPDU.getSW() == 0x6984) { - status = STATUS.NOT_ACTIV; - } else if (responseAPDU.getSW() == 0x63c0) { - status = STATUS.BLOCKED; - } else if (responseAPDU.getSW1() == 0x63) { - status = STATUS.ACTIV; - } - if (log.isDebugEnabled()) { - log.debug("PIN " + pinSpec.getLocalizedName() + " status: " + SMCCHelper.toString(responseAPDU.getBytes())); + STATUS status = STATUS.UNKNOWN; + if (responseAPDU.getSW() == 0x6984) { + status = STATUS.NOT_ACTIV; + } else if (responseAPDU.getSW() == 0x63c0) { + status = STATUS.BLOCKED; + } else if (responseAPDU.getSW1() == 0x63) { + status = STATUS.ACTIV; + } + if (log.isDebugEnabled()) { + log.debug("PIN " + pinSpec.getLocalizedName() + + " status: " + SMCCHelper.toString(responseAPDU.getBytes())); + } + pinStatuses.put(pinSpec, status); } + return pinStatuses; - pinStatuses.put(pinSpec, status); - } -// icc.endExclusive(); - - return pinStatuses; - - } catch (CardException ex) { - log.error("Failed to get PIN status: " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); - } finally { - try { - icc.endExclusive(); } catch (CardException ex) { - log.trace("failed to end exclusive card access"); + log.error("Failed to get PIN status: " + ex.getMessage(), ex); + throw new GetPINStatusException(ex.getMessage()); + } finally { + try { + icc.endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); + } + } + } else { + for (PINSpec pinSpec : pins) { + pinStatuses.put(pinSpec, STATUS.UNKNOWN); } } + return pinStatuses; } - private void showPINManagementDialog(PINManagementGUIFacade gui) { - try { - Map pins = getPINStatuses(); - gui.showPINManagementDialog(pins, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", - this, "cancel"); - } catch (SignatureCardException ex) { - gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN_WITH_PARAM, - new Object[]{ex.getMessage()}, - this, "cancel"); + /** + * query status for STARCOS card, + * assume provided status for ACOS card + * @param pinSpec + * @param status + * @throws at.gv.egiz.smcc.SignatureCardException if query status fails + */ + private void updatePINStatus(PINSpec pinSpec, STATUS status) throws GetPINStatusException { + if (card instanceof STARCOSCard) { + Card icc = card.getCard(); + try { + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + byte kid = pinSpec.getKID(); + byte[] contextAID = pinSpec.getContextAID(); + + if (contextAID != null) { + CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); + ResponseAPDU responseAPDU = channel.transmit(selectAPDU); + if (responseAPDU.getSW() != 0x9000) { + icc.endExclusive(); + String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new GetPINStatusException(msg); + } + } + + CommandAPDU verifyAPDU = new CommandAPDU(new byte[] { + (byte) 0x00, (byte) 0x20, (byte) 00, kid }); + ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); + + status = STATUS.UNKNOWN; + if (responseAPDU.getSW() == 0x6984) { + status = STATUS.NOT_ACTIV; + } else if (responseAPDU.getSW() == 0x63c0) { + status = STATUS.BLOCKED; + } else if (responseAPDU.getSW1() == 0x63) { + status = STATUS.ACTIV; + } + if (log.isDebugEnabled()) { + log.debug(pinSpec.getLocalizedName() + + " status: " + SMCCHelper.toString(responseAPDU.getBytes())); + } + pinStatuses.put(pinSpec, status); + + } catch (CardException ex) { + log.error("Failed to get PIN status: " + ex.getMessage(), ex); + throw new GetPINStatusException(ex.getMessage()); + } finally { + try { + icc.endExclusive(); + } catch (CardException ex) { + log.warn("failed to end exclusive card access: " + ex.getMessage()); + } + } + } else { + pinStatuses.put(pinSpec, status); } } } diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties index 430f85b5..69d231f7 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -18,6 +18,7 @@ title.pin.mgmt=PIN Verwaltung title.activate.pin=PIN Aktivieren title.change.pin=PIN \u00C4ndern title.unblock.pin=PIN Entsperren +title.verify.pin=PIN Eingeben title.activate.success=Erfolg title.change.success=Erfolg @@ -25,6 +26,7 @@ message.pin.mgmt=Die Karte verf\u00FCgt \u00FCber {0} PINs message.activate.pin={0} eingeben und best\u00E4tigen message.change.pin={0} eingeben und best\u00E4tigen message.unblock.pin=PUK zu {0} eingeben +message.verify.pin={0} eingeben (TODO: Warning not activated) message.activate.success={0} wurde erfolgreich aktiviert. message.change.success={0} wurde erfolgreich ge\u00E4ndert. @@ -38,14 +40,19 @@ label.repeat.pin=Best\u00E4tigung: button.activate=Aktivieren button.change=\u00C4ndern button.unblock=Entsperren +button.verify=Abfragen help.activation=help.activation help.pin.mgmt=help.pin.mgmt +err.status=Der Status der PINs konnte nicht \u00FCberpr\u00FCft werden. err.activate=Beim Aktivieren der {0} trat ein Fehler auf. err.change=Beim \u00C4ndern der {0} trat ein Fehler auf. err.unblock=Das Entsperren der {0} wird nicht unterst\u00FCtzt. +err.verify=VERIFY ERROR (TODO) err.retries=Falscher {0}, noch {1} Versuche +err.locked={0} gesperrt. +err.not.active={0} nicht aktiviert. status.not.active=NICHT AKTIV status.active=AKTIV diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties index 98d18633..920f7d5b 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -38,14 +38,18 @@ label.repeat.pin=Confirmation: button.activate=Activate button.change=Change button.unblock=Unblock +button.verify=Query help.activation=help.activation help.pin.mgmt=help.pin.mgmt +err.status=PIN statuses could not be read. err.activate=An error occured during the activation of {0}. err.change=An error occured during the changing of {0}. err.unblock=Unblocking of {0} is not supported. err.retries=Wrong {0}, {1} tries remaining +err.locked={0} locked +err.not.active={0} not activated. status.not.active=NOT ACTIVE status.active=ACTIVE diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java index a28ee1eb..1714017e 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java @@ -124,4 +124,10 @@ public class BKUGuiProxy implements BKUGUIFacade { showDialog(); delegate.showHashDataInputDialog(signedReferences, okListener, okCommand); } + + @Override + public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams, ActionListener okListener, String okCommand) { + showDialog(); + delegate.showMessageDialog(titleKey, msgKey, msgParams, okListener, okCommand); + } } diff --git a/BKUOnline/src/test/resources/commons-logging.properties b/BKUOnline/src/test/resources/commons-logging.properties new file mode 100644 index 00000000..0d497b1b --- /dev/null +++ b/BKUOnline/src/test/resources/commons-logging.properties @@ -0,0 +1,16 @@ +# Copyright 2008 Federal Chancellery Austria and +# Graz University of Technology +# +# 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. + +org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger diff --git a/BKUOnline/src/test/resources/log4j.properties b/BKUOnline/src/test/resources/log4j.properties new file mode 100644 index 00000000..b30aa40a --- /dev/null +++ b/BKUOnline/src/test/resources/log4j.properties @@ -0,0 +1,29 @@ +# Copyright 2008 Federal Chancellery Austria and +# Graz University of Technology +# +# 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. + + +#log4j.rootLogger=INFO, STDOUT, file +log4j.rootLogger=DEBUG, STDOUT +log4j.logger.at.gv.egiz.bku.slcommands=TRACE, STDOUT +log4j.logger.at.gv.egiz.bku.binding=TRACE, STDOUT +#log4j.logger.at.gv = INFO + + +# STDOUT appender +log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender +log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout +#log4j.appender.STDOUT.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %20c | %10t | %m%n +#log4j.appender.STDOUT.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n +log4j.appender.STDOUT.layout.ConversionPattern=%-5p | %t | %c %x - %m%n diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java index 57925240..c2c62fd8 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -31,6 +31,7 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.util.SMCCHelper; import java.nio.charset.Charset; +import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -334,8 +335,8 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } @Override - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { - + protected int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { + CardChannel channel = getCardChannel(); ResponseAPDU resp; @@ -343,13 +344,17 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { if (pin != null) { resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, encodePINBlock(pin)), false); } else { + //TODO this is not supported resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid), false); } } catch (CardException ex) { log.error("smart card communication failed: " + ex.getMessage()); throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); } - + + //6A 00 (falshe P1/P2) nicht in contextAID + //69 85 (nutzungsbedingungen nicht erfüllt) in DF_Sig und nicht sigpin + if (resp.getSW() == 0x63c0) { throw new LockedException("PIN locked."); } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { @@ -363,7 +368,6 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { throw new SignatureCardException("Failed to verify pin: SW=" + Integer.toHexString(resp.getSW()) + "."); } - } private void mseSetDST(int p1, int p2, byte[] dst) throws CardException, SignatureCardException { @@ -432,8 +436,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { * @param pin * @return a 8 byte pin block */ - @Override - public byte[] encodePINBlock(String pin) { + private byte[] encodePINBlock(String pin) { byte[] asciiPIN = pin.getBytes(Charset.forName("ASCII")); byte[] encodedPIN = new byte[8]; System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, @@ -443,7 +446,72 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } @Override - public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { + public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { throw new SignatureCardException("PIN activation not supported by this card"); } + + /** + * SCARD_E_NOT_TRANSACTED inf/dec PIN not active (pcsc crash) + * @param pinSpec + * @param oldPIN + * @param newPIN + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.VerificationFailedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + @Override + public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) + throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { + Card icc = getCard(); + try { + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + if (pinSpec.getContextAID() != null) { + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); + if (responseAPDU.getSW() != 0x9000) { + icc.endExclusive(); + String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new SignatureCardException(msg); + } + } + + byte[] cmd = new byte[16]; + System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); + System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); + + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x00, pinSpec.getKID(), cmd), false); + + icc.endExclusive(); + + log.debug("change pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + + if (responseAPDU.getSW() == 0x63c0) { + log.error(pinSpec.getLocalizedName() + " locked"); + throw new LockedException(); + } else if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { + int retries = responseAPDU.getSW2() & 0x0f; + log.error("wrong " + pinSpec.getLocalizedName() + ", " + retries + " retries"); + throw new VerificationFailedException(retries); + } else if (responseAPDU.getSW() == 0x6983) { + // sig-pin only (card not transacted for inf/dec pin) + log.error(pinSpec.getLocalizedName() + " not activated"); + throw new NotActivatedException(); + } else if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to change " + pinSpec.getLocalizedName() + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new SignatureCardException(msg); + } + } catch (CardException ex) { + log.error("Failed to change " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } + } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java index 63301bd1..39952bb9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -37,6 +37,8 @@ import java.util.List; import java.util.Locale; import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; @@ -117,8 +119,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException; - // made public -// protected abstract int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException; + protected abstract int verifyPIN(String pin, byte kid) + throws LockedException, NotActivatedException, SignatureCardException; protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { @@ -321,7 +323,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { throw new VerificationFailedException(retries); } } - + return readBinaryTLV(maxLength, (byte) 0x30); @@ -443,53 +445,40 @@ public abstract class AbstractSignatureCard implements SignatureCard { return pinSpecs; } - public void changePIN(byte kid, byte[] contextAID, String oldPIN, String newPIN) throws SignatureCardException, VerificationFailedException { + @Override + public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { + Card icc = getCard(); try { icc.beginExclusive(); CardChannel channel = icc.getBasicChannel(); - if (contextAID != null) { + if (pinSpec.getContextAID() != null) { ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID)); + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); if (responseAPDU.getSW() != 0x9000) { icc.endExclusive(); - String msg = "Failed to change PIN " + SMCCHelper.toString(new byte[]{kid}) + - ": Failed to select AID " + SMCCHelper.toString(contextAID) + + String msg = "Failed to verify PIN " + + SMCCHelper.toString(new byte[]{pinSpec.getKID()}) + + ": Failed to verify AID " + + SMCCHelper.toString(pinSpec.getContextAID()) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); log.error(msg); throw new SignatureCardException(msg); } } + return verifyPIN(pin, pinSpec.getKID()); - byte[] cmd = new byte[16]; - System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); - System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); - - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0x24, 0x00, kid, cmd), false); - - icc.endExclusive(); - - if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { - int retries = responseAPDU.getSW2() & 0x0f; - log.error("Failed VERIFY PIN, " + retries + " tries left"); - throw new VerificationFailedException(retries); - } - if (responseAPDU.getSW() != 0x9000) { - String msg = "Failed to change PIN " - + SMCCHelper.toString(new byte[]{kid}) + ": " - + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); + } catch (CardException ex) { + log.error("failed to verify pinspec: " + ex.getMessage(), ex); + throw new SignatureCardException(ex); + } finally { + try { + icc.endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); } - } catch (CardException ex) { - log.error("Failed to change PIN: " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); } } - - abstract byte[] encodePINBlock(String pin); - } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java index b1288f74..3c5f38a2 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -512,7 +512,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard throw new LockedException(); } else if (resp.getSW() == 0x6984) { // PIN LCS = "Initialized" (-> not activated) - throw new NotActivatedException("PIN not set."); + throw new NotActivatedException(); } else if (resp.getSW() == 0x9000) { return -1; // success } else { @@ -552,8 +552,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard * @return a 8 byte pin block consisting of length byte (0x2X), * the BCD encoded pin and a 0xFF padding */ - @Override - public byte[] encodePINBlock(String pin) { + private byte[] encodePINBlock(String pin) { char[] pinChars = pin.toCharArray(); int numDigits = pinChars.length; int numBytes = (int) Math.ceil(numDigits/2.0); @@ -572,37 +571,108 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard return pinBlock; } - public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { + @Override + public void activatePIN(PINSpec pinSpec, String pin) + throws SignatureCardException { Card icc = getCard(); try { icc.beginExclusive(); CardChannel channel = icc.getBasicChannel(); - if (contextAID != null) { + if (pinSpec.getContextAID() != null) { ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID)); + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); if (responseAPDU.getSW() != 0x9000) { icc.endExclusive(); - String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + - ": Failed to select AID " + SMCCHelper.toString(contextAID) + - ": " + SMCCHelper.toString(responseAPDU.getBytes()); + String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); log.error(msg); throw new SignatureCardException(msg); } } ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0x24, 0x01, kid, encodePINBlock(pin)), false); + new CommandAPDU(0x00, 0x24, 0x01, pinSpec.getKID(), encodePINBlock(pin)), + false); icc.endExclusive(); - if (responseAPDU.getSW() != 0x9000) { - String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); + log.debug("activate pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + + if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to activate " + pinSpec.getLocalizedName() + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new SignatureCardException(msg); + } + } catch (CardException ex) { + log.error("Failed to activate " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } + } + + /** + * activates pin (newPIN) if not active + * @param pinSpec + * @param oldPIN + * @param newPIN + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.VerificationFailedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + @Override + public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) + throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { + Card icc = getCard(); + try { + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + if (pinSpec.getContextAID() != null) { + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); + if (responseAPDU.getSW() != 0x9000) { + icc.endExclusive(); + String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); + log.error(msg); + throw new SignatureCardException(msg); + } + } + + byte[] cmd = new byte[16]; + System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); + System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); + + ResponseAPDU responseAPDU = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x00, pinSpec.getKID(), cmd), false); + + icc.endExclusive(); + + log.debug("change pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + + // activates pin (newPIN) if not active + if (responseAPDU.getSW() == 0x63c0) { + log.error(pinSpec.getLocalizedName() + " locked"); + throw new LockedException(); + } else if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { + int retries = responseAPDU.getSW2() & 0x0f; + log.error("wrong " + pinSpec.getLocalizedName() + ", " + retries + " retries"); + throw new VerificationFailedException(retries); + } else if (responseAPDU.getSW() == 0x6983) { + log.error(pinSpec.getLocalizedName() + " locked"); + throw new LockedException(); + } else if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to change " + pinSpec.getLocalizedName() + + ": SW=" + Integer.toHexString(responseAPDU.getSW()); log.error(msg); throw new SignatureCardException(msg); } } catch (CardException ex) { - log.error("Failed to activate PIN: " + ex.getMessage()); + log.error("Failed to change " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); throw new SignatureCardException(ex.getMessage(), ex); } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java index 57aeb994..d7763be0 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -393,22 +393,21 @@ public class SWCard implements SignatureCard { public void reset() throws SignatureCardException { } - @Override - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { - return -1; - } - @Override public List getPINSpecs() { return new ArrayList(); } @Override - public void changePIN(byte kid, byte[] contextAID, String oldPIN, String newPIN) throws SignatureCardException, VerificationFailedException { + public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { + return -1; } @Override - public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { + public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { } + @Override + public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { + } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index a88593bc..3c2273b9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -125,21 +125,20 @@ public interface SignatureCard { /** * + * @param pinSpec descriptor which pin to verify * @param pin may be null to test the PIN status - * @param kid * @return the number of remaining retries or -1 * @throws at.gv.egiz.smcc.LockedException * @throws at.gv.egiz.smcc.NotActivatedException * @throws at.gv.egiz.smcc.SignatureCardException */ - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException; + public int verifyPIN(PINSpec pinSpec, String pin) + throws LockedException, NotActivatedException, SignatureCardException; - public void changePIN(byte kid, byte[] contextAID, - String oldPIN, String newPIN) - throws SignatureCardException, VerificationFailedException; + public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) + throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException; - public void activatePIN(byte kid, byte[] contextAID, - String pin) + public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException; /** diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java index a5d6df23..b2a91784 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -88,13 +88,21 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements @Override - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { - return 0; + public List getPINSpecs() { + return new ArrayList(); } @Override - public List getPINSpecs() { - return new ArrayList(); + public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { + return -1; + } + + @Override + public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { + } + + @Override + public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { } }; diff --git a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java index c03f17cd..3ae1d0ff 100644 --- a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java +++ b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java @@ -28,7 +28,7 @@ public interface NamespacePrefix { String SAML10_PREFIX = "saml"; String SL_PREFIX = "sl"; String XADES_PREFIX = "xades"; - String XMLDSIG_PREFIX = "xmldsig"; + String XMLDSIG_PREFIX = "dsig"; String XSI_PREFIX = "xsi"; } -- cgit v1.2.3 From 18932bb8a7ebf805026701416389e08bdb0d6dae Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 10 Mar 2009 13:36:20 +0000 Subject: do not return errorResponse on interrupt git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@318 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'smccSTAL/src') diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 3691156e..1cf81e05 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -101,7 +101,7 @@ public abstract class AbstractSMCCSTAL implements STAL { return null; } } catch (InterruptedException e) { - log.info("Interrupt in handleRequest, do not retry"); + log.info("Interrupt during request handling, do not retry"); throw e; } catch (Exception e) { log.info("Error while handling STAL request:", e); @@ -140,8 +140,8 @@ public abstract class AbstractSMCCSTAL implements STAL { } } } catch (InterruptedException ex) { - log.error("got interrupted, return ErrorResponse 6001"); - throw new RuntimeException(ex); + log.error("interrupted during request handling"); + throw new RuntimeException("interrupted during request handling", ex); } } -- cgit v1.2.3 From 2a1df5e58e44f8d77f34eb80df74e8c0d27caceb Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 18 Mar 2009 22:27:28 +0000 Subject: 1.1-rc5 (pinProviderFactories, gui refactoring, signatureCard, secureViewer) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@322 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/online/applet/AppletBKUWorker.java | 5 +- .../bku/online/applet/AppletHashDataDisplay.java | 217 -------- .../egiz/bku/online/applet/AppletSecureViewer.java | 221 ++++++++ .../java/at/gv/egiz/bku/gui/PINManagementGUI.java | 365 +++++++------- .../at/gv/egiz/bku/gui/PINManagementGUIFacade.java | 46 +- .../bku/online/applet/PINManagementBKUWorker.java | 10 +- .../smccstal/ext/ManagementPINProviderFactory.java | 53 ++ .../smccstal/ext/PINManagementRequestHandler.java | 319 ++++++------ .../bku/smccstal/ext/PinpadPINProviderFactory.java | 126 +++++ .../smccstal/ext/SoftwarePINProviderFactory.java | 148 ++++++ .../gv/egiz/bku/gui/ActivationMessages.properties | 17 +- .../egiz/bku/gui/ActivationMessages_en.properties | 15 +- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 4 +- .../gv/egiz/bku/smccstal/ext/FileSystemTest.java | 435 ---------------- .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 66 ++- .../main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java | 560 +++++++++++---------- .../main/java/at/gv/egiz/bku/gui/PinDocument.java | 30 +- .../at/gv/egiz/bku/gui/Messages.properties | 28 +- .../at/gv/egiz/bku/gui/Messages_en.properties | 28 +- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 6 +- .../at/gv/egiz/bku/local/stal/BKUGuiProxy.java | 106 ++-- .../bku/local/stal/LocalSignRequestHandler.java | 4 +- .../java/at/gv/egiz/bku/local/app/Container.java | 5 - .../main/webapp/helpfiles/de/cardnotsupported.html | 47 ++ .../main/webapp/helpfiles/de/cardnotsupported.png | Bin 0 -> 2120 bytes .../webapp/helpfiles/de/help.cardnotsupported.html | 47 -- .../webapp/helpfiles/de/help.cardnotsupported.png | Bin 2120 -> 0 bytes .../main/webapp/helpfiles/de/help.insertcard.html | 42 -- .../main/webapp/helpfiles/de/help.insertcard.png | Bin 2270 -> 0 bytes .../src/main/webapp/helpfiles/de/help.wait.html | 39 -- .../src/main/webapp/helpfiles/de/help.wait.png | Bin 1542 -> 0 bytes .../src/main/webapp/helpfiles/de/help.welcome.html | 40 -- .../src/main/webapp/helpfiles/de/help.welcome.png | Bin 1537 -> 0 bytes .../src/main/webapp/helpfiles/de/insertcard.html | 42 ++ .../src/main/webapp/helpfiles/de/insertcard.png | Bin 0 -> 2270 bytes BKUOnline/src/main/webapp/helpfiles/de/wait.html | 39 ++ BKUOnline/src/main/webapp/helpfiles/de/wait.png | Bin 0 -> 1542 bytes .../src/main/webapp/helpfiles/de/welcome.html | 40 ++ BKUOnline/src/main/webapp/helpfiles/de/welcome.png | Bin 0 -> 1537 bytes smcc/src/main/java/at/gv/egiz/smcc/ACOS04Card.java | 30 ++ smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 410 ++++++++++----- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 352 +++++++++++-- .../java/at/gv/egiz/smcc/ChangePINProvider.java | 39 ++ .../src/main/java/at/gv/egiz/smcc/PINProvider.java | 26 +- .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 479 +++++++++++------- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 36 +- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 42 +- .../java/at/gv/egiz/smcc/SignatureCardFactory.java | 2 +- .../java/at/gv/egiz/smcc/TimeoutException.java | 39 ++ smcc/src/test/resources/log4j.properties | 2 +- .../at/gv/egiz/bku/smccstal/AbstractBKUWorker.java | 8 +- .../gv/egiz/bku/smccstal/AbstractPINProvider.java | 67 +++ .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 6 + .../bku/smccstal/InfoBoxReadRequestHandler.java | 40 +- .../gv/egiz/bku/smccstal/PINProviderFactory.java | 47 ++ .../bku/smccstal/PinpadPINProviderFactory.java | 155 ++++++ .../java/at/gv/egiz/bku/smccstal/SecureViewer.java | 44 ++ .../gv/egiz/bku/smccstal/SignRequestHandler.java | 149 +++--- .../bku/smccstal/SoftwarePINProviderFactory.java | 140 ++++++ .../java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java | 16 +- 60 files changed, 3278 insertions(+), 2001 deletions(-) delete mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java create mode 100644 BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/SoftwarePINProviderFactory.java delete mode 100644 BKUAppletExt/src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java create mode 100644 BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.html create mode 100644 BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.png delete mode 100644 BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.html delete mode 100644 BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.png delete mode 100644 BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.html delete mode 100644 BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.png delete mode 100644 BKUOnline/src/main/webapp/helpfiles/de/help.wait.html delete mode 100644 BKUOnline/src/main/webapp/helpfiles/de/help.wait.png delete mode 100644 BKUOnline/src/main/webapp/helpfiles/de/help.welcome.html delete mode 100644 BKUOnline/src/main/webapp/helpfiles/de/help.welcome.png create mode 100644 BKUOnline/src/main/webapp/helpfiles/de/insertcard.html create mode 100644 BKUOnline/src/main/webapp/helpfiles/de/insertcard.png create mode 100644 BKUOnline/src/main/webapp/helpfiles/de/wait.html create mode 100644 BKUOnline/src/main/webapp/helpfiles/de/wait.png create mode 100644 BKUOnline/src/main/webapp/helpfiles/de/welcome.html create mode 100644 BKUOnline/src/main/webapp/helpfiles/de/welcome.png create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ACOS04Card.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/TimeoutException.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PinpadPINProviderFactory.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SoftwarePINProviderFactory.java (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java index eb6cf30b..9b9735f6 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java @@ -60,14 +60,15 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { @Override public void run() { - gui.showWelcomeDialog(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WELCOME, + BKUGUIFacade.MESSAGE_WELCOME); try { STALPortType stalPort = applet.getSTALPort(); STALTranslator stalTranslator = applet.getSTALTranslator(); addRequestHandler(SignRequest.class, - new AppletHashDataDisplay(stalPort, sessionId)); + new AppletSecureViewer(stalPort, sessionId)); GetNextRequestResponseType nextRequestResp = stalPort.connect(sessionId); diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java deleted file mode 100644 index 2ed9aa5b..00000000 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletHashDataDisplay.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * 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 at.gv.egiz.bku.online.applet; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.smccstal.SignRequestHandler; -import at.gv.egiz.stal.HashDataInput; -import at.gv.egiz.stal.impl.ByteArrayHashDataInput; -import at.gv.egiz.stal.service.GetHashDataInputFault; -import at.gv.egiz.stal.service.STALPortType; -import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; -import at.gv.egiz.stal.service.types.GetHashDataInputType; -import at.gv.egiz.stal.signedinfo.ReferenceType; -import java.security.NoSuchAlgorithmException; - -/** - * A SignRequesthandler that obtains hashdata inputs from a STAL webservice and - * displays these either within the applet or in a separate frame. - * The internal viewer displays plaintext data only, other mimetypes can be saved to disk. - * The standalone (frame) viewer displays all mimetypes. - * - * (This class depends on STALService and therefore is not part of BKUCommonGUI.) - * - * @author Clemens Orthacker - */ -public class AppletHashDataDisplay extends SignRequestHandler { - - private static final Log log = LogFactory.getLog(AppletHashDataDisplay.class); - protected STALPortType stalPort; - protected String sessId; - - public AppletHashDataDisplay(STALPortType stalPort, String sessId) { - if (stalPort == null || sessId == null) { - throw new NullPointerException("STAL port must not be null"); - } - this.sessId = sessId; - this.stalPort = stalPort; - } - - /** - * TODO don't throw exceptions - * @param signedReferences - * @throws java.security.DigestException - * @throws java.lang.Exception - */ - @Override - public void displayHashDataInputs(List signedReferences) throws DigestException, Exception { - - List hdi = getHashDataInput(signedReferences); - List verifiedHashDataInputs = verifyHashDataInput(signedReferences, hdi); - - if (verifiedHashDataInputs.size() > 0) { - gui.showHashDataInputDialog(verifiedHashDataInputs, this, "hashDataDone"); - } else { - throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); - } - } - - /** - * Get all hashdata inputs that contain an ID attribute but no Type attribute. - * @param signedReferences - * @return - * @throws at.gv.egiz.stal.service.GetHashDataInputFault - */ - private List getHashDataInput(List signedReferences) throws GetHashDataInputFault, Exception { - GetHashDataInputType request = new GetHashDataInputType(); - request.setSessionId(sessId); - -// HashMap idSignedRefMap = new HashMap(); - for (ReferenceType signedRef : signedReferences) { - //don't get Manifest, QualifyingProperties, ... - if (signedRef.getType() == null) { - String signedRefId = signedRef.getId(); - if (signedRefId != null) { - if (log.isTraceEnabled()) { - log.trace("requesting hashdata input for reference " + signedRefId); - } -// idSignedRefMap.put(signedRefId, signedRef); - GetHashDataInputType.Reference ref = new GetHashDataInputType.Reference(); - ref.setID(signedRefId); - request.getReference().add(ref); - - } else { - throw new Exception("Cannot resolve signature data for dsig:Reference without Id attribute"); - } - } - } - - if (request.getReference().size() < 1) { - log.error("No signature data (apart from any QualifyingProperties or a Manifest) for session " + sessId); - throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); - } - - if (log.isDebugEnabled()) { - log.debug("WebService call GetHashDataInput for " + request.getReference().size() + " references in session " + sessId); - } - GetHashDataInputResponseType response = stalPort.getHashDataInput(request); - return response.getReference(); - } - - /** - * Verifies all signed references and returns STAL HashDataInputs - * @param signedReferences - * @param hashDataInputs - * @return - * @throws java.security.DigestException - * @throws java.security.NoSuchAlgorithmException - * @throws Exception if no hashdata input is provided for a signed reference - */ - private List verifyHashDataInput(List signedReferences, List hashDataInputs) throws DigestException, NoSuchAlgorithmException, Exception { - - ArrayList verifiedHashDataInputs = new ArrayList(); - - for (ReferenceType signedRef : signedReferences) { - if (signedRef.getType() == null) { - log.info("Verifying digest for signed reference " + signedRef.getId()); - - String signedRefId = signedRef.getId(); - byte[] signedDigest = signedRef.getDigestValue(); - String signedDigestAlg = null; - if (signedRef.getDigestMethod() != null) { - signedDigestAlg = signedRef.getDigestMethod().getAlgorithm(); - } else { - throw new NoSuchAlgorithmException("Failed to verify digest value for reference " + signedRefId + ": no digest algorithm"); - } - - // usually, there is just one item here - GetHashDataInputResponseType.Reference hashDataInput = null; - for (GetHashDataInputResponseType.Reference hdi : hashDataInputs) { - if (signedRefId.equals(hdi.getID())) { - hashDataInput = hdi; - break; - } - } - if (hashDataInput == null) { - throw new Exception("No hashdata input for reference " + signedRefId + " returned by service"); - } - - byte[] hdi = hashDataInput.getValue(); - String mimeType = hashDataInput.getMimeType(); - String encoding = hashDataInput.getEncoding(); - - if (hdi == null) { - throw new Exception("No hashdata input for reference " + signedRefId + " provided by service"); - } - if (log.isDebugEnabled()) { - log.debug("Got HashDataInput " + signedRefId + " (" + mimeType + ";" + encoding + ")"); - } - - byte[] hashDataInputDigest = digest(hdi, signedDigestAlg); - - if (log.isDebugEnabled()) { - log.debug("Comparing digest values... "); - } -// log.warn("***************** DISABLED HASHDATA VERIFICATION"); - if (!Arrays.equals(hashDataInputDigest, signedDigest)) { - log.error("Bad digest value for reference " + signedRefId); - throw new DigestException("Bad digest value for reference " + signedRefId); - } - - verifiedHashDataInputs.add(new ByteArrayHashDataInput(hdi, signedRefId, mimeType, encoding)); - } - } - - return verifiedHashDataInputs; - } - - //TODO - private byte[] digest(byte[] hashDataInput, String mdAlg) throws NoSuchAlgorithmException { - if ("http://www.w3.org/2000/09/xmldsig#sha1".equals(mdAlg)) { - mdAlg = "SHA-1"; - } else if ("http://www.w3.org/2001/04/xmlenc#sha256".equals(mdAlg)) { - mdAlg = "SHA-256"; - } else if ("http://www.w3.org/2001/04/xmlenc#sha224".equals(mdAlg)) { - mdAlg = "SHA-224"; - } else if ("http://www.w3.org/2001/04/xmldsig-more#sha224".equals(mdAlg)) { - mdAlg = "SHA-224"; - } else if ("http://www.w3.org/2001/04/xmldsig-more#sha384".equals(mdAlg)) { - mdAlg = "SHA-384"; - } else if ("http://www.w3.org/2001/04/xmlenc#sha512".equals(mdAlg)) { - mdAlg = "SHA-512"; - } else if ("http://www.w3.org/2001/04/xmldsig-more#md2".equals(mdAlg)) { - mdAlg = "MD2"; - } else if ("http://www.w3.org/2001/04/xmldsig-more#md5".equals(mdAlg)) { - mdAlg = "MD5"; - } else if ("http://www.w3.org/2001/04/xmlenc#ripemd160".equals(mdAlg)) { - mdAlg = "RipeMD-160"; - } else { - throw new NoSuchAlgorithmException("Failed to verify digest value: unsupported digest algorithm " + mdAlg); - } - - MessageDigest md = MessageDigest.getInstance(mdAlg); - return md.digest(hashDataInput); - } -} diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java new file mode 100644 index 00000000..e2551e2d --- /dev/null +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java @@ -0,0 +1,221 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.online.applet; + +import at.gv.egiz.bku.smccstal.SecureViewer; +import java.security.DigestException; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.smccstal.SignRequestHandler; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; +import at.gv.egiz.stal.service.GetHashDataInputFault; +import at.gv.egiz.stal.service.STALPortType; +import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; +import at.gv.egiz.stal.service.types.GetHashDataInputType; +import at.gv.egiz.stal.signedinfo.ReferenceType; +import java.security.NoSuchAlgorithmException; + +/** + * A SignRequesthandler that obtains hashdata inputs from a STAL webservice and + * displays these either within the applet or in a separate frame. + * The internal viewer displays plaintext data only, other mimetypes can be saved to disk. + * The standalone (frame) viewer displays all mimetypes. + * + * (This class depends on STALService and therefore is not part of BKUCommonGUI.) + * + * @author Clemens Orthacker + */ +public class AppletSecureViewer extends SignRequestHandler { + + private static final Log log = LogFactory.getLog(AppletSecureViewer.class); + protected STALPortType stalPort; + protected String sessId; + + public AppletSecureViewer(STALPortType stalPort, String sessId) { + if (stalPort == null || sessId == null) { + throw new NullPointerException("STAL port must not be null"); + } + this.sessId = sessId; + this.stalPort = stalPort; + } + + /** + * TODO don't throw exceptions + * @param signedReferences + * @throws java.security.DigestException + * @throws java.lang.Exception + */ + @Override + public void displayDataToBeSigned(List signedReferences) + throws DigestException, Exception { + + List hdi = getHashDataInput(signedReferences); + List verifiedHashDataInputs = verifyHashDataInput(signedReferences, hdi); + + if (verifiedHashDataInputs.size() > 0) { + gui.showSecureViewer(verifiedHashDataInputs, this, "hashDataDone"); + } else { + throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); + } + } + + /** + * Get all hashdata inputs that contain an ID attribute but no Type attribute. + * @param signedReferences + * @return + * @throws at.gv.egiz.stal.service.GetHashDataInputFault + */ + private List getHashDataInput(List signedReferences) + throws GetHashDataInputFault, Exception { + GetHashDataInputType request = new GetHashDataInputType(); + request.setSessionId(sessId); + +// HashMap idSignedRefMap = new HashMap(); + for (ReferenceType signedRef : signedReferences) { + //don't get Manifest, QualifyingProperties, ... + if (signedRef.getType() == null) { + String signedRefId = signedRef.getId(); + if (signedRefId != null) { + if (log.isTraceEnabled()) { + log.trace("requesting hashdata input for reference " + signedRefId); + } +// idSignedRefMap.put(signedRefId, signedRef); + GetHashDataInputType.Reference ref = new GetHashDataInputType.Reference(); + ref.setID(signedRefId); + request.getReference().add(ref); + + } else { + throw new Exception("Cannot resolve signature data for dsig:Reference without Id attribute"); + } + } + } + + if (request.getReference().size() < 1) { + log.error("No signature data (apart from any QualifyingProperties or a Manifest) for session " + sessId); + throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); + } + + if (log.isDebugEnabled()) { + log.debug("WebService call GetHashDataInput for " + request.getReference().size() + " references in session " + sessId); + } + GetHashDataInputResponseType response = stalPort.getHashDataInput(request); + return response.getReference(); + } + + /** + * Verifies all signed references and returns STAL HashDataInputs + * @param signedReferences + * @param hashDataInputs + * @return + * @throws java.security.DigestException + * @throws java.security.NoSuchAlgorithmException + * @throws Exception if no hashdata input is provided for a signed reference + */ + private List verifyHashDataInput(List signedReferences, List hashDataInputs) + throws DigestException, NoSuchAlgorithmException, Exception { + + ArrayList verifiedHashDataInputs = new ArrayList(); + + for (ReferenceType signedRef : signedReferences) { + if (signedRef.getType() == null) { + log.info("Verifying digest for signed reference " + signedRef.getId()); + + String signedRefId = signedRef.getId(); + byte[] signedDigest = signedRef.getDigestValue(); + String signedDigestAlg = null; + if (signedRef.getDigestMethod() != null) { + signedDigestAlg = signedRef.getDigestMethod().getAlgorithm(); + } else { + throw new NoSuchAlgorithmException("Failed to verify digest value for reference " + signedRefId + ": no digest algorithm"); + } + + // usually, there is just one item here + GetHashDataInputResponseType.Reference hashDataInput = null; + for (GetHashDataInputResponseType.Reference hdi : hashDataInputs) { + if (signedRefId.equals(hdi.getID())) { + hashDataInput = hdi; + break; + } + } + if (hashDataInput == null) { + throw new Exception("No hashdata input for reference " + signedRefId + " returned by service"); + } + + byte[] hdi = hashDataInput.getValue(); + String mimeType = hashDataInput.getMimeType(); + String encoding = hashDataInput.getEncoding(); + + if (hdi == null) { + throw new Exception("No hashdata input for reference " + signedRefId + " provided by service"); + } + if (log.isDebugEnabled()) { + log.debug("Got HashDataInput " + signedRefId + " (" + mimeType + ";" + encoding + ")"); + } + + byte[] hashDataInputDigest = digest(hdi, signedDigestAlg); + + if (log.isDebugEnabled()) { + log.debug("Comparing digest values... "); + } +// log.warn("***************** DISABLED HASHDATA VERIFICATION"); + if (!Arrays.equals(hashDataInputDigest, signedDigest)) { + log.error("Bad digest value for reference " + signedRefId); + throw new DigestException("Bad digest value for reference " + signedRefId); + } + + verifiedHashDataInputs.add(new ByteArrayHashDataInput(hdi, signedRefId, mimeType, encoding)); + } + } + + return verifiedHashDataInputs; + } + + //TODO + private byte[] digest(byte[] hashDataInput, String mdAlg) throws NoSuchAlgorithmException { + if ("http://www.w3.org/2000/09/xmldsig#sha1".equals(mdAlg)) { + mdAlg = "SHA-1"; + } else if ("http://www.w3.org/2001/04/xmlenc#sha256".equals(mdAlg)) { + mdAlg = "SHA-256"; + } else if ("http://www.w3.org/2001/04/xmlenc#sha224".equals(mdAlg)) { + mdAlg = "SHA-224"; + } else if ("http://www.w3.org/2001/04/xmldsig-more#sha224".equals(mdAlg)) { + mdAlg = "SHA-224"; + } else if ("http://www.w3.org/2001/04/xmldsig-more#sha384".equals(mdAlg)) { + mdAlg = "SHA-384"; + } else if ("http://www.w3.org/2001/04/xmlenc#sha512".equals(mdAlg)) { + mdAlg = "SHA-512"; + } else if ("http://www.w3.org/2001/04/xmldsig-more#md2".equals(mdAlg)) { + mdAlg = "MD2"; + } else if ("http://www.w3.org/2001/04/xmldsig-more#md5".equals(mdAlg)) { + mdAlg = "MD5"; + } else if ("http://www.w3.org/2001/04/xmlenc#ripemd160".equals(mdAlg)) { + mdAlg = "RipeMD-160"; + } else { + throw new NoSuchAlgorithmException("Failed to verify digest value: unsupported digest algorithm " + mdAlg); + } + + MessageDigest md = MessageDigest.getInstance(mdAlg); + return md.digest(hashDataInput); + } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java index c904be0c..159dd29d 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -56,8 +56,6 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac /** remember the pinSpec to return to worker */ protected PINSpec pinSpec; - protected enum DIALOG { VERIFY, ACTIVATE, CHANGE, UNBLOCK }; - public PINManagementGUI(Container contentPane, Locale locale, Style guiStyle, @@ -235,43 +233,110 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac } @Override - public void showActivatePINDialog(final PINSpec pin, - final ActionListener okListener, final String okCommand, - final ActionListener cancelListener, final String cancelCommand) { - log.debug("scheduling activate pin dialog"); - showPINDialog(DIALOG.ACTIVATE, pin, okListener, okCommand, cancelListener, cancelCommand); + public void showPINDialog(DIALOG type, PINSpec pinSpec, + ActionListener okListener, String okCommand, + ActionListener cancelListener, String cancelCommand) { + showPINDialog(type, pinSpec, -1, false, + okListener, okCommand, cancelListener, cancelCommand); + } + + @Override + public void showPINDialog(DIALOG type, PINSpec pinSpec, int retries, + ActionListener okListener, String okCommand, + ActionListener cancelListener, String cancelCommand) { + showPINDialog(type, pinSpec, retries, false, + okListener, okCommand, cancelListener, cancelCommand); } + @Override + public void showPinpadPINDialog(DIALOG type, PINSpec pinSpec, int retries) { + String title, msg; + Object[] params; + if (retries < 0) { + params = new Object[2]; + if (shortText) { + params[0] = "PIN"; + } else { + params[0] = pinSpec.getLocalizedName(); + } + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params[1] = pinSize; + if (type == DIALOG.CHANGE) { + log.debug("show change pin dialog"); + title = TITLE_CHANGE_PIN; + msg = MESSAGE_CHANGEPIN_PINPAD; + } else if (type == DIALOG.ACTIVATE) { + log.debug("show activate pin dialog"); + title = TITLE_ACTIVATE_PIN; + msg = MESSAGE_ENTERPIN_PINPAD; + } else if (type == DIALOG.VERIFY) { + log.debug("show verify pin dialog"); + title = TITLE_VERIFY_PIN; + msg = MESSAGE_ENTERPIN_PINPAD; + } else { + log.debug("show unblock pin dialog"); + title = TITLE_UNBLOCK_PIN; + msg = MESSAGE_ENTERPIN_PINPAD; + } + + } else { + log.debug("show retry pin dialog"); + title = TITLE_RETRY; + msg = (retries < 2) ? + MESSAGE_LAST_RETRY : MESSAGE_RETRIES; + params = new Object[] {String.valueOf(retries)}; + } + showMessageDialog(title, msg, params); + } private void showPINDialog(final DIALOG type, final PINSpec pinSpec, + final int retries, final boolean pinpad, final ActionListener okListener, final String okCommand, final ActionListener cancelListener, final String cancelCommand) { + log.debug("scheduling pin dialog"); + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - String HELP_TOPIC, TITLE, MESSAGE_MGMT; + String HELP_TOPIC, TITLE, MESSAGE_MGMT, MESSAGE_MGMT_PARAM; HELP_TOPIC = HELP_PINMGMT; - if (type == DIALOG.CHANGE) { - log.debug("show change pin dialog"); - TITLE = TITLE_CHANGE_PIN; - MESSAGE_MGMT = MESSAGE_CHANGE_PIN; - } else if (type == DIALOG.ACTIVATE) { - log.debug("show activate pin dialog"); - TITLE = TITLE_ACTIVATE_PIN; - MESSAGE_MGMT = MESSAGE_ACTIVATE_PIN; - oldPinField = null; - } else if (type == DIALOG.VERIFY) { - log.debug("show verify pin dialog"); - TITLE = TITLE_VERIFY_PIN; - MESSAGE_MGMT = MESSAGE_VERIFY_PIN; + if (retries < 0) { + if (type == DIALOG.CHANGE) { + log.debug("show change pin dialog"); + TITLE = TITLE_CHANGE_PIN; + MESSAGE_MGMT = MESSAGE_CHANGE_PIN; + } else if (type == DIALOG.ACTIVATE) { + log.debug("show activate pin dialog"); + TITLE = TITLE_ACTIVATE_PIN; + MESSAGE_MGMT = MESSAGE_ACTIVATE_PIN; + oldPinField = null; + } else if (type == DIALOG.VERIFY) { + log.debug("show verify pin dialog"); + TITLE = TITLE_VERIFY_PIN; + MESSAGE_MGMT = MESSAGE_VERIFY_PIN; + } else { + log.debug("show unblock pin dialog"); + TITLE = TITLE_UNBLOCK_PIN; + MESSAGE_MGMT = MESSAGE_UNBLOCK_PIN; + } + if (shortText) { + MESSAGE_MGMT_PARAM = "PIN"; + } else { + MESSAGE_MGMT_PARAM = pinSpec.getLocalizedName(); + } } else { - log.debug("show unblock pin dialog"); - TITLE = TITLE_UNBLOCK_PIN; - MESSAGE_MGMT = MESSAGE_UNBLOCK_PIN; + log.debug("show retry pin dialog"); + TITLE = TITLE_RETRY; + MESSAGE_MGMT = (retries < 2) ? + MESSAGE_LAST_RETRY : MESSAGE_RETRIES; + MESSAGE_MGMT_PARAM = String.valueOf(retries); } mainPanel.removeAll(); @@ -280,24 +345,67 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac helpListener.setHelpTopic(HELP_TOPIC); JLabel mgmtLabel = new JLabel(); - mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); + if (retries < 0) { + mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); + } else { + mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() | Font.BOLD)); + mgmtLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); + } if (renderHeaderPanel) { titleLabel.setText(getMessage(TITLE)); String mgmtPattern = getMessage(MESSAGE_MGMT); - if (shortText) { - mgmtLabel.setText(MessageFormat.format(mgmtPattern, "PIN")); - } else { - mgmtLabel.setText(MessageFormat.format(mgmtPattern, pinSpec.getLocalizedName())); - } + mgmtLabel.setText(MessageFormat.format(mgmtPattern, MESSAGE_MGMT_PARAM)); } else { mgmtLabel.setText(getMessage(TITLE)); } + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + + //////////////////////////////////////////////////////////////// + // COMMON LAYOUT SECTION + //////////////////////////////////////////////////////////////// + + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(mgmtLabel); + GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(mgmtLabel); + + if (!renderHeaderPanel) { + infoHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + infoVertical + .addComponent(helpLabel); + } + + GroupLayout.ParallelGroup pinHorizontal; + GroupLayout.SequentialGroup pinVertical; + + if (pinpad) { + JLabel pinpadLabel = new JLabel(); + pinpadLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); + String pinpadPattern = getMessage(MESSAGE_PINPAD); + pinpadLabel.setText(MessageFormat.format(pinpadPattern, + new Object[] { pinSpec.getLocalizedName(), pinSize })); + + pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(pinpadLabel); + pinVertical = mainPanelLayout.createSequentialGroup() + .addComponent(pinpadLabel); + } else { + JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~Font.BOLD)); okButton.setText(getMessage(BUTTON_OK)); - okButton.setEnabled(type == DIALOG.VERIFY && pinSpec.getMinLength() == 0); + okButton.setEnabled(pinSpec.getMinLength() <= 0); okButton.setActionCommand(okCommand); okButton.addActionListener(okListener); @@ -334,7 +442,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac repeatPinLabel.setText(MessageFormat.format(repeatPinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); repeatPinField.setText(""); - repeatPinField.setDocument(new PINDocument(pinSpec, okButton, pinField.getDocument())); +// repeatPinField.setDocument(new PINDocument(pinSpec, okButton, pinField.getDocument())); repeatPinField.setActionCommand(okCommand); repeatPinField.addActionListener(new ActionListener() { @@ -365,7 +473,15 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac } } }); - } // else -> ACTIVATE (not verify, not change) + + repeatPinField.setDocument(new PINDocument( + pinSpec, okButton, + pinField.getDocument(), oldPinField.getDocument())); + } else { + // else -> ACTIVATE (not verify, not change) + repeatPinField.setDocument(new PINDocument( + pinSpec, okButton, pinField.getDocument())); + } } else { pinField.setDocument(new PINDocument(pinSpec, okButton)); } @@ -373,30 +489,14 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac JLabel pinsizeLabel = new JLabel(); pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~Font.BOLD, pinsizeLabel.getFont().getSize()-2)); String pinsizePattern = getMessage(LABEL_PINSIZE); - String pinSize = String.valueOf(pinSpec.getMinLength()); - if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { - pinSize += "-" + pinSpec.getMaxLength(); - } pinsizeLabel.setText(MessageFormat.format(pinsizePattern, new Object[]{pinSize})); - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(mgmtLabel); - GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(mgmtLabel); - - if (!renderHeaderPanel) { - infoHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - infoVertical - .addComponent(helpLabel); - } + //////////////////////////////////////////////////////////////// + // NON-PINPAD SPECIFIC LAYOUT SECTION + //////////////////////////////////////////////////////////////// - GroupLayout.ParallelGroup pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); - GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup(); + pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + pinVertical = mainPanelLayout.createSequentialGroup(); // if (pinLabelPos == PinLabelPosition.ABOVE) { // if (changePin) { @@ -495,7 +595,38 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); pinVertical .addComponent(pinsizeLabel); -// } + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + GroupLayout.Group buttonVertical; + + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + cancelButton.setText(getMessage(BUTTON_CANCEL)); + cancelButton.setActionCommand(cancelCommand); + cancelButton.addActionListener(cancelListener); + + buttonHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(okButton) + .addComponent(cancelButton); + + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); + buttonPanelLayout.setVerticalGroup(buttonVertical); + + if (oldPinField != null) { + oldPinField.requestFocusInWindow(); + } else { + pinField.requestFocusInWindow(); + } + + } // END NON-PINPAD SECTION mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) @@ -508,132 +639,12 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addGroup(pinVertical)); - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); - GroupLayout.Group buttonVertical; - - JButton cancelButton = new JButton(); - cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - cancelButton.setText(getMessage(BUTTON_CANCEL)); - cancelButton.setActionCommand(cancelCommand); - cancelButton.addActionListener(cancelListener); - - buttonHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); - buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(okButton) - .addComponent(cancelButton); - - buttonPanelLayout.setHorizontalGroup(buttonHorizontal); - buttonPanelLayout.setVerticalGroup(buttonVertical); - - if (oldPinField != null) { - oldPinField.requestFocusInWindow(); - } else { - pinField.requestFocusInWindow(); - } contentPanel.validate(); } }); } - @Override - public void showChangePINDialog(final PINSpec pin, - final ActionListener okListener, final String okCommand, - final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling change pin dialog"); - showPINDialog(DIALOG.CHANGE, pin, okListener, okCommand, cancelListener, cancelCommand); - } - - @Override - public void showUnblockPINDialog(final PINSpec pin, - final ActionListener okListener, final String okCommand, - final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling unblock PIN dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show unblock PIN dialog"); - - log.error("unblock pin not supported"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_ERROR)); - } - - helpListener.setHelpTopic(HELP_PINMGMT); - - String errorMsgPattern = getMessage(ERR_UNBLOCK); - String errorMsg = MessageFormat.format(errorMsgPattern, pin.getLocalizedName()); - - JLabel errorMsgLabel = new JLabel(); - errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - errorMsgLabel.setText(errorMsg); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); - GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup(); - - if (!renderHeaderPanel) { - JLabel errorTitleLabel = new JLabel(); - errorTitleLabel.setFont(errorTitleLabel.getFont().deriveFont(errorTitleLabel.getFont().getStyle() | java.awt.Font.BOLD)); - errorTitleLabel.setText(getMessage(TITLE_ERROR)); - errorTitleLabel.setForeground(ERROR_COLOR); - - mainHorizontal - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(errorTitleLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)); - mainVertical - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(errorTitleLabel) - .addComponent(helpLabel)); - } - - mainPanelLayout.setHorizontalGroup(mainHorizontal - .addComponent(errorMsgLabel)); - mainPanelLayout.setVerticalGroup(mainVertical - .addComponent(errorMsgLabel)); - - JButton okButton = new JButton(); - okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - okButton.setText(getMessage(BUTTON_OK)); - okButton.setActionCommand(cancelCommand); - okButton.addActionListener(cancelListener); - - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(okButton)); - - contentPanel.validate(); - } - }); - } - @Override protected int initButtonSize() { int bs = super.initButtonSize(); @@ -659,8 +670,4 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac return bs; } - @Override - public void showVerifyPINDialog(PINSpec pin, ActionListener okListener, String okCmd, ActionListener cancelListener, String cancelCmd) { - showPINDialog(DIALOG.VERIFY, pin, okListener, okCmd, cancelListener, cancelCmd); - } } diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java index 9c630431..45313f42 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -35,13 +35,18 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String TITLE_UNBLOCK_PIN = "title.unblock.pin"; public static final String TITLE_ACTIVATE_SUCCESS = "title.activate.success"; public static final String TITLE_CHANGE_SUCCESS = "title.change.success"; - public static final String MESSAGE_ACTIVATE_SUCCESS = "message.activate.success"; - public static final String MESSAGE_CHANGE_SUCCESS = "message.change.success"; - public static final String MESSAGE_PINMGMT = "message.pin.mgmt"; - public static final String MESSAGE_ACTIVATE_PIN = "message.activate.pin"; - public static final String MESSAGE_CHANGE_PIN = "message.change.pin"; - public static final String MESSAGE_VERIFY_PIN = "message.verify.pin"; - public static final String MESSAGE_UNBLOCK_PIN = "message.unblock.pin"; + + // removed message.* prefix to reuse keys as help keys + public static final String MESSAGE_ACTIVATE_SUCCESS = "activate.success"; + public static final String MESSAGE_CHANGE_SUCCESS = "change.success"; + public static final String MESSAGE_PINMGMT = "pin.mgmt"; + public static final String MESSAGE_PINPAD = "pinpad"; + public static final String MESSAGE_CHANGEPIN_PINPAD = "pinpad.change"; + public static final String MESSAGE_ACTIVATE_PIN = "activate.pin"; + public static final String MESSAGE_CHANGE_PIN = "change.pin"; + public static final String MESSAGE_VERIFY_PIN = "verify.pin"; + public static final String MESSAGE_UNBLOCK_PIN = "unblock.pin"; + public static final String LABEL_OLD_PIN = "label.old.pin"; public static final String LABEL_NEW_PIN = "label.new.pin"; public static final String LABEL_REPEAT_PIN = "label.repeat.pin"; @@ -66,26 +71,37 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String STATUS_UNKNOWN = "status.unknown"; public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED, UNKNOWN }; + public enum DIALOG { VERIFY, ACTIVATE, CHANGE, UNBLOCK }; public void showPINManagementDialog(Map pins, ActionListener activateListener, String activateCmd, String changeCmd, String unblockCmd, String verifyCmd, ActionListener cancelListener, String cancelCmd); - public void showActivatePINDialog(PINSpec pin, + public void showPINDialog(DIALOG type, PINSpec pin, ActionListener okListener, String okCmd, ActionListener cancelListener, String cancelCmd); - public void showChangePINDialog(PINSpec pin, + public void showPINDialog(DIALOG type, PINSpec pin, int retries, ActionListener okListener, String okCmd, ActionListener cancelListener, String cancelCmd); - public void showUnblockPINDialog(PINSpec pin, - ActionListener okListener, String okCmd, - ActionListener cancelListener, String cancelCmd); + public void showPinpadPINDialog(DIALOG type, PINSpec pin, int retries); - public void showVerifyPINDialog(PINSpec pin, - ActionListener okListener, String okCmd, - ActionListener cancelListener, String cancelCmd); +// public void showActivatePINDialog(PINSpec pin, +// ActionListener okListener, String okCmd, +// ActionListener cancelListener, String cancelCmd); +// +// public void showChangePINDialog(PINSpec pin, +// ActionListener okListener, String okCmd, +// ActionListener cancelListener, String cancelCmd); +// +// public void showUnblockPINDialog(PINSpec pin, +// ActionListener okListener, String okCmd, +// ActionListener cancelListener, String cancelCmd); +// +// public void showVerifyPINDialog(PINSpec pin, +// ActionListener okListener, String okCmd, +// ActionListener cancelListener, String cancelCmd); public char[] getOldPin(); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java index 85892026..81b635f8 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java @@ -42,7 +42,8 @@ public class PINManagementBKUWorker extends AppletBKUWorker { @Override public void run() { - gui.showWelcomeDialog(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WELCOME, + BKUGUIFacade.MESSAGE_WELCOME); try { List responses = handleRequest(Collections.singletonList(new PINManagementRequest())); @@ -53,7 +54,6 @@ public class PINManagementBKUWorker extends AppletBKUWorker { log.debug("PIN management dialog terminated"); } else if (response instanceof ErrorResponse) { log.debug("PIN management dialog terminated with error"); - showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, null); } else { throw new RuntimeException("Invalid STAL response: " + response.getClass().getName()); } @@ -62,7 +62,11 @@ public class PINManagementBKUWorker extends AppletBKUWorker { } } catch (RuntimeException ex) { - log.error("unexpected error: " + ex.getMessage(), ex); + log.error(ex.getMessage()); + Throwable cause = ex.getCause(); + if (cause != null) { // && cause instanceof InterruptedException) { + log.info(cause.getMessage()); + } showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, null); } catch (Exception ex) { log.error(ex.getMessage(), ex); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java new file mode 100644 index 00000000..b0dd8766 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal.ext; + +import at.gv.egiz.smcc.ChangePINProvider; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.SignatureCard; + +/** + * + * @author Clemens Orthacker + */ +public abstract class ManagementPINProviderFactory { +// extends at.gv.egiz.bku.smccstal.PINProviderFactory { + + PINManagementGUIFacade gui; + + public static ManagementPINProviderFactory getInstance(SignatureCard forCard, + PINManagementGUIFacade gui) { +// if (forCard.ifdSupportsFeature(SignatureCard.FEATURE_VERIFY_PIN_DIRECT)) { +//// forCard.ifdSupportsFeature(SignatureCard.FEATURE_MODIFY_PIN_DIRECT) +// return new PinpadPINProviderFactory(gui); +// +// } else { + return new SoftwarePINProviderFactory(gui); +// } + } + + public abstract PINProvider getVerifyPINProvider(); + + public abstract PINProvider getActivatePINProvider(); + + public abstract ChangePINProvider getChangePINProvider(); + + public abstract PINProvider getUnblockPINProvider(); + +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java index 66db0484..6b565b26 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java @@ -18,13 +18,19 @@ package at.gv.egiz.bku.smccstal.ext; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade.DIALOG; import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; import at.gv.egiz.bku.smccstal.AbstractRequestHandler; +import at.gv.egiz.bku.smccstal.PINProviderFactory; +import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.PINProvider; import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.smcc.STARCOSCard; +import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.TimeoutException; import at.gv.egiz.smcc.VerificationFailedException; import at.gv.egiz.smcc.util.SMCCHelper; import at.gv.egiz.stal.ErrorResponse; @@ -35,8 +41,6 @@ import at.gv.egiz.stal.ext.PINManagementResponse; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; @@ -53,7 +57,8 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { protected static final Log log = LogFactory.getLog(PINManagementRequestHandler.class); - Map pinStatuses; + protected Map pinStatuses; + private ManagementPINProviderFactory pinProviderFactory; @Override public STALResponse handleRequest(STALRequest request) throws InterruptedException { @@ -61,9 +66,12 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { PINManagementGUIFacade gui = (PINManagementGUIFacade) this.gui; + PINSpec selectedPIN = null; + try { - pinStatuses = getPINStatuses(); + pinStatuses = getPINStatuses(); + gui.showPINManagementDialog(pinStatuses, this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", this, "cancel"); @@ -74,175 +82,100 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { if ("cancel".equals(actionCommand)) { return new PINManagementResponse(); - } else if ("back".equals(actionCommand)) { - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); } else { - PINSpec selectedPIN = gui.getSelectedPINSpec(); + selectedPIN = gui.getSelectedPINSpec(); if (selectedPIN == null) { - throw new RuntimeException("no PIN selected for activation/change"); + throw new NullPointerException("no PIN selected for activation/change"); } - if ("activate_enterpin".equals(actionCommand)) { - gui.showActivatePINDialog(selectedPIN, - this, "activate", this, "back"); - } else if ("change_enterpin".equals(actionCommand)) { - gui.showChangePINDialog(selectedPIN, - this, "change", this, "back"); - } else if ("unblock_enterpuk".equals(actionCommand)) { - gui.showUnblockPINDialog(selectedPIN, - this, "unblock", this, "back"); - } else if ("verify_enterpin".equals(actionCommand)) { - gui.showVerifyPINDialog(selectedPIN, - this, "verify", this, "back"); - } else if ("activate".equals(actionCommand)) { - try { - log.debug("activate " + selectedPIN.getLocalizedName()); - card.activatePIN(selectedPIN, - String.valueOf(gui.getPin())); + if (pinProviderFactory == null) { + pinProviderFactory = + ManagementPINProviderFactory.getInstance(card, gui); + } + + try { + if ("activate_enterpin".equals(actionCommand)) { + log.info("activate " + selectedPIN.getLocalizedName()); + card.activatePIN(selectedPIN, + pinProviderFactory.getActivatePINProvider()); updatePINStatus(selectedPIN, STATUS.ACTIV); gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, new Object[] {selectedPIN.getLocalizedName()}, - this, "ok"); + BKUGUIFacade.BUTTON_OK, this, "ok"); waitForAction(); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (GetPINStatusException ex) { - log.error("failed to get " + selectedPIN.getLocalizedName() + - " status: " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, - this, "cancel"); - } catch (SignatureCardException ex) { - log.error("failed to activate " + selectedPIN.getLocalizedName() + - ": " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_ACTIVATE, - new Object[] {selectedPIN.getLocalizedName()}, - this, "cancel"); - } - } else if ("change".equals(actionCommand)) { - log.info("change " + selectedPIN.getLocalizedName()); - try { - card.changePIN(selectedPIN, - String.valueOf(gui.getOldPin()), - String.valueOf(gui.getPin())); + } else if ("change_enterpin".equals(actionCommand)) { + log.info("change " + selectedPIN.getLocalizedName()); + card.changePIN(selectedPIN, + pinProviderFactory.getChangePINProvider()); updatePINStatus(selectedPIN, STATUS.ACTIV); gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, new Object[] {selectedPIN.getLocalizedName()}, - this, "ok"); - waitForAction(); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (GetPINStatusException ex) { - log.error("failed to get " + selectedPIN.getLocalizedName() + - " status: " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, - this, "cancel"); - } catch (LockedException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + - ": PIN locked"); - updatePINStatus(selectedPIN, STATUS.BLOCKED); - gui.showErrorDialog(PINManagementGUIFacade.ERR_LOCKED, - new Object[] {selectedPIN.getLocalizedName()}, - this, "ok"); - waitForAction(); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (VerificationFailedException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + - ": " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_RETRIES, - new Object[] {selectedPIN.getLocalizedName(), ex.getRetries()}, - this, "change_enterpin"); - } catch (NotActivatedException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + - ": PIN not active"); - updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); - gui.showErrorDialog(PINManagementGUIFacade.ERR_NOT_ACTIVE, - new Object[] {selectedPIN.getLocalizedName()}, - this, "ok"); + BKUGUIFacade.BUTTON_OK, this, "ok"); waitForAction(); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (SignatureCardException ex) { - log.error("failed to change " + selectedPIN.getLocalizedName() + - ": " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_CHANGE, - new Object[] {selectedPIN.getLocalizedName()}, - this, "cancel"); - } - } else if ("unblock".equals(actionCommand)) { - log.info("unblock " + selectedPIN.getLocalizedName()); - log.error("unblock PIN not implemented"); - gui.showErrorDialog(PINManagementGUIFacade.ERR_UNBLOCK, null, this, "cancel"); - } else if ("verify".equals(actionCommand)) { - try { + + } else if ("unblock_enterpuk".equals(actionCommand)) { + log.info("unblock " + selectedPIN.getLocalizedName()); + card.unblockPIN(selectedPIN, + pinProviderFactory.getUnblockPINProvider()); + } else if ("verify_enterpin".equals(actionCommand)) { log.info("verify " + selectedPIN.getLocalizedName()); - int retries = card.verifyPIN(selectedPIN, String.valueOf(gui.getPin())); - log.trace(retries + " retries"); - if (retries < 0) { - updatePINStatus(selectedPIN, STATUS.ACTIV); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } else { - log.error("failed to verify " + selectedPIN.getLocalizedName() + - ": " + retries + " retries left"); - gui.showErrorDialog(PINManagementGUIFacade.ERR_RETRIES, - new Object[] {selectedPIN.getLocalizedName(), retries}, - this, "verify_enterpin"); - } - } catch (GetPINStatusException ex) { - log.error("failed to get " + selectedPIN.getLocalizedName() + - " status: " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, - this, "cancel"); - } catch (LockedException ex) { - log.error("failed to verify " + selectedPIN.getLocalizedName() + - ": PIN locked"); - updatePINStatus(selectedPIN, STATUS.BLOCKED); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (NotActivatedException ex) { - log.error("failed to verify " + selectedPIN.getLocalizedName() + - ": PIN not active"); - updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); - gui.showPINManagementDialog(pinStatuses, - this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", - this, "cancel"); - } catch (SignatureCardException ex) { - log.error("failed to verify " + selectedPIN.getLocalizedName() + - ": " + ex.getMessage()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, - new Object[] {selectedPIN.getLocalizedName()}, - this, "cancel"); + card.verifyPIN(selectedPIN, + pinProviderFactory.getVerifyPINProvider()); + updatePINStatus(selectedPIN, STATUS.ACTIV); } - - } else { - throw new RuntimeException("unsupported action " + actionCommand); + } catch (CancelledException ex) { + log.trace("cancelled"); + } catch (TimeoutException ex) { + log.error("Timeout during pin entry"); + gui.showMessageDialog(BKUGUIFacade.TITLE_ENTRY_TIMEOUT, + BKUGUIFacade.ERR_PIN_TIMEOUT, + new Object[] {selectedPIN.getLocalizedName()}, + BKUGUIFacade.BUTTON_OK, this, null); + waitForAction(); + } catch (LockedException ex) { + log.error(selectedPIN.getLocalizedName() + " locked"); + updatePINStatus(selectedPIN, STATUS.BLOCKED); + gui.showErrorDialog(PINManagementGUIFacade.ERR_LOCKED, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (NotActivatedException ex) { + log.error(selectedPIN.getLocalizedName() + " not active"); + updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); + gui.showErrorDialog(PINManagementGUIFacade.ERR_NOT_ACTIVE, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); } - } - } + } // end if + + selectedPIN = null; + gui.showPINManagementDialog(pinStatuses, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); + } // end while + } catch (GetPINStatusException ex) { - log.error("Failed to get PIN statuses: " + ex.getMessage()); + String pin = (selectedPIN != null) ? selectedPIN.getLocalizedName() : "pin"; + log.error("failed to get " + pin + " status: " + ex.getMessage()); gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, this, "ok"); waitForAction(); return new ErrorResponse(1000); + } catch (SignatureCardException ex) { + log.error(ex.getMessage(), ex); + gui.showErrorDialog(PINManagementGUIFacade.ERR_UNKNOWN, null, + this, "ok"); + waitForAction(); + return new ErrorResponse(1000); } } else { log.error("Got unexpected STAL request: " + request); return new ErrorResponse(1000); } - } @Override @@ -375,4 +308,100 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { pinStatuses.put(pinSpec, status); } } + +// /** +// * provides oldPin and newPin from one dialog, +// * and don't know whether providePIN() or provideOldPIN() is called first. +// */ +// class SoftwarePinProvider implements PINProvider { +// +// private PINManagementGUIFacade.DIALOG type; +// private boolean retry = false; +// +// private char[] newPin; +// private char[] oldPin; +// +// public SoftwarePinProvider(DIALOG type) { +// this.type = type; +// } +// +// @Override +// public char[] providePIN(PINSpec spec, int retries) +// throws CancelledException, InterruptedException { +// if (newPin == null) { +// getPINs(spec, retries); +// } +// char[] pin = newPin; +// newPin = null; +// return pin; +// } +// +// @Override +// public char[] provideOldPIN(PINSpec spec, int retries) +// throws CancelledException, InterruptedException { +// if (oldPin == null) { +// getPINs(spec, retries); +// } +// char[] pin = oldPin; +// oldPin = null; +// return pin; +// } +// +// private void getPINs(PINSpec spec, int retries) +// throws InterruptedException, CancelledException { +// PINManagementGUIFacade gui = +// (PINManagementGUIFacade) PINManagementRequestHandler.this.gui; +// +// if (retry) { +// gui.showPINDialog(type, spec, retries, +// PINManagementRequestHandler.this, "exec", +// PINManagementRequestHandler.this, "back"); +// } else { +// gui.showPINDialog(type, spec, +// PINManagementRequestHandler.this, "exec", +// PINManagementRequestHandler.this, "back"); +// } +// waitForAction(); +// +// if (actionCommand.equals("exec")) { +// gui.showWaitDialog(null); +// retry = true; +// oldPin = gui.getOldPin(); +// newPin = gui.getPin(); +// } else if (actionCommand.equals("back")) { +// throw new CancelledException(); +// } else { +// log.error("unsupported command " + actionCommand); +// throw new CancelledException(); +// } +// } +// } +// +// +// class PinpadPinProvider implements PINProvider { +// +// private PINManagementGUIFacade.DIALOG type; +// private boolean retry = false; +// +// public PinpadPinProvider(DIALOG type) { +// this.type = type; +// } +// +// @Override +// public char[] providePIN(PINSpec spec, int retries) { +// log.debug("provide pin for " + type); +// if (retry) { +// ((PINManagementGUIFacade) gui).showPinpadPINDialog(type, spec, retries); +// } else { +// ((PINManagementGUIFacade) gui).showPinpadPINDialog(type, spec, -1); +// retry = true; +// } +// return null; +// } +// +// @Override +// public char[] provideOldPIN(PINSpec spec, int retries) { +// return null; +// } +// } } diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java new file mode 100644 index 00000000..4176e0a9 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java @@ -0,0 +1,126 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal.ext; + +import at.gv.egiz.smcc.ChangePINProvider; +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade.DIALOG; +import at.gv.egiz.bku.smccstal.AbstractPINProvider; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; + +/** + * + * @author Clemens Orthacker + */ +public class PinpadPINProviderFactory extends ManagementPINProviderFactory { + + protected PinpadPINProviderFactory(PINManagementGUIFacade gui) { + this.gui = gui; + } + + @Override + public PINProvider getVerifyPINProvider() { + return new SimplePinProvider(DIALOG.VERIFY); + } + + @Override + public PINProvider getActivatePINProvider() { + return new SimplePinProvider(DIALOG.ACTIVATE); + } + + @Override + public ChangePINProvider getChangePINProvider() { + return new SimplePinProvider(DIALOG.CHANGE); + } + + @Override + public PINProvider getUnblockPINProvider() { + return new SimplePinProvider(DIALOG.UNBLOCK); + } + + + class SimplePinProvider extends AbstractPINProvider + implements ChangePINProvider { + +// protected PINManagementGUIFacade gui; + protected PINManagementGUIFacade.DIALOG type; + + private SimplePinProvider(PINManagementGUIFacade.DIALOG type) { + this.type = type; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + showPinpadPINDialog(retries, spec); + retry = true; + return null; + +// gui.showPINDialog(type, spec, (retry) ? retries : -1, +// this, "exec", +// this, "back"); +// +// waitForAction(); +// +// if ("exec".equals(action)) { +// gui.showWaitDialog(null); +// retry = true; +// return gui.getPin(); +// } else if ("back".equals(action)) { +// throw new CancelledException(); +// } else { +// log.error("unsupported command " + action); +// throw new CancelledException(); +// } + } + + /** + * do not call this method without calling providePIN() + * (no message is displayed) + * @param spec + * @param retries + * @return + */ + @Override + public char[] provideOldPIN(PINSpec spec, int retries) { + return null; + } + + private void showPinpadPINDialog(int retries, PINSpec pinSpec) { + String title, message; + Object[] params; + if (retry) { + title = BKUGUIFacade.TITLE_RETRY; + message = BKUGUIFacade.MESSAGE_RETRIES; + params = new Object[]{String.valueOf(retries)}; + } else { + title = BKUGUIFacade.TITLE_SIGN; + message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } + gui.showMessageDialog(title, message, params); + } + } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/SoftwarePINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/SoftwarePINProviderFactory.java new file mode 100644 index 00000000..e87512d0 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/SoftwarePINProviderFactory.java @@ -0,0 +1,148 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal.ext; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.ChangePINProvider; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade.DIALOG; +import at.gv.egiz.bku.smccstal.AbstractPINProvider; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; + +/** + * + * @author Clemens Orthacker + */ +public class SoftwarePINProviderFactory extends ManagementPINProviderFactory { + + protected SoftwarePINProviderFactory(PINManagementGUIFacade gui) { + this.gui = gui; + } + + @Override + public PINProvider getVerifyPINProvider() { + return new SimplePinProvider(DIALOG.VERIFY); + } + + @Override + public PINProvider getActivatePINProvider() { + return new SimplePinProvider(DIALOG.ACTIVATE); + } + + @Override + public ChangePINProvider getChangePINProvider() { + return new ChangePinProvider(); + } + + @Override + public PINProvider getUnblockPINProvider() { + return new SimplePinProvider(DIALOG.UNBLOCK); + } + + class SimplePinProvider extends AbstractPINProvider { + +// protected PINManagementGUIFacade gui; + protected PINManagementGUIFacade.DIALOG type; + + private SimplePinProvider(DIALOG type) { + this.type = type; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + gui.showPINDialog(type, spec, (retry) ? retries : -1, + this, "exec", + this, "back"); + + waitForAction(); + + if ("exec".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + retry = true; + return gui.getPin(); + } else if ("back".equals(action)) { + throw new CancelledException(); + } else { + log.error("unsupported command " + action); + throw new CancelledException(); + } + } + } + + class ChangePinProvider extends AbstractPINProvider + implements ChangePINProvider { + +// protected PINManagementGUIFacade gui; + + private char[] oldPin; + private char[] newPin; + + private ChangePinProvider() { + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (newPin == null) { + getPINs(spec, retries); + } + char[] pin = newPin; + newPin = null; + return pin; + } + + @Override + public char[] provideOldPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (oldPin == null) { + getPINs(spec, retries); + } + char[] pin = oldPin; + oldPin = null; + return pin; + } + + private void getPINs(PINSpec spec, int retries) + throws InterruptedException, CancelledException { + + gui.showPINDialog(PINManagementGUIFacade.DIALOG.CHANGE, spec, + (retry) ? retries : -1, + this, "exec", + this, "back"); + + waitForAction(); + + if ("exec".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + retry = true; + oldPin = gui.getOldPin(); + newPin = gui.getPin(); + } else if ("back".equals(action)) { + throw new CancelledException(); + } else { + log.error("unsupported command " + action); + throw new CancelledException(); + } + } + } +} diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties index 69d231f7..4ceacb21 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -22,13 +22,16 @@ title.verify.pin=PIN Eingeben title.activate.success=Erfolg title.change.success=Erfolg -message.pin.mgmt=Die Karte verf\u00FCgt \u00FCber {0} PINs -message.activate.pin={0} eingeben und best\u00E4tigen -message.change.pin={0} eingeben und best\u00E4tigen -message.unblock.pin=PUK zu {0} eingeben -message.verify.pin={0} eingeben (TODO: Warning not activated) -message.activate.success={0} wurde erfolgreich aktiviert. -message.change.success={0} wurde erfolgreich ge\u00E4ndert. +# removed message.* prefix to reuse keys as help keys +pin.mgmt=Die Karte verf\u00FCgt \u00FCber {0} PINs +pinpad={0} ({1} stellig) am Kartenleser eingeben und best\u00E4tigen. +pinpad.change={0} ({1} stellig) am Kartenleser eingeben und best\u00E4tigen. +activate.pin={0} eingeben und best\u00E4tigen +change.pin={0} eingeben und best\u00E4tigen +unblock.pin=PUK zu {0} eingeben +verify.pin={0} eingeben (TODO: Warning not activated) +activate.success={0} wurde erfolgreich aktiviert. +change.success={0} wurde erfolgreich ge\u00E4ndert. label.activation=e-card Aktivierungsprozess label.activation.step=Schritt {0} diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties index 920f7d5b..9178d65c 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -21,12 +21,15 @@ title.unblock.pin=Unblock PIN title.activate.success=Success title.change.success=Success -message.pin.mgmt=The smartcard has {0} PINs -message.activate.pin=Enter and confirm {0} -message.change.pin=Enter and confirm {0} -message.unblock.pin=Enter PUK for {0} -message.activate.success={0} successfully activated -message.change.success={0} successfully changed +# removed message.* prefix to reuse keys as help keys +pin.mgmt=The smartcard has {0} PINs +pinpad=Enter {0} ({1} digits) on pinpad and confirm. +pinpad.change=Enter {0} ({1} digits) on pinpad and confirm. +activate.pin=Enter and confirm {0} +change.pin=Enter and confirm {0} +unblock.pin=Enter PUK for {0} +activate.success={0} successfully activated +change.success={0} successfully changed label.activation=e-card activation process label.activation.step=Step {0} diff --git a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index ef8c87e4..b01abe72 100644 --- a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -74,7 +74,7 @@ public class BKUGUIWorker implements Runnable { @Override public void actionPerformed(ActionEvent e) { - gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", null, "hashdata"); + gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", null, "hashdata"); } }; HashDataInput signedRef1 = new ByteArrayHashDataInput( @@ -112,7 +112,7 @@ public class BKUGUIWorker implements Runnable { // signedRefs.add(signedRef4); // signedRefs.add(signedRef4); // signedRefs = Collections.singletonList(signedRef1); - gui.showHashDataInputDialog(signedRefs, returnListener, "return"); + gui.showSecureViewer(signedRefs, returnListener, "return"); } }; diff --git a/BKUAppletExt/src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java b/BKUAppletExt/src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java deleted file mode 100644 index 5fa3cbd7..00000000 --- a/BKUAppletExt/src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * 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 at.gv.egiz.bku.smccstal.ext; - -import at.gv.egiz.smcc.FileNotFoundException; -import at.gv.egiz.smcc.LockedException; -import at.gv.egiz.smcc.NotActivatedException; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.smcc.SignatureCard; -import at.gv.egiz.smcc.SignatureCardException; -import at.gv.egiz.smcc.util.SMCCHelper; -import at.gv.egiz.smcc.util.SmartCardIO; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Locale; -import java.util.Map; -import javax.smartcardio.Card; -import javax.smartcardio.CardChannel; -import javax.smartcardio.CardException; -import javax.smartcardio.CardTerminal; -import javax.smartcardio.CommandAPDU; -import javax.smartcardio.ResponseAPDU; -import org.junit.Ignore; -import org.junit.Test; -import static org.junit.Assert.*; - -/** - * - * @author Clemens Orthacker - */ -@Ignore -public class FileSystemTest { - - /** asign premium */ - public static final byte[] AID_DEC = new byte[] { (byte) 0xA0, (byte) 0x00, - (byte) 0x00, (byte) 0x01, (byte) 0x18, (byte) 0x45, (byte) 0x4E }; - - @Test -// @Ignore - public void testCard() throws CardException, SignatureCardException, InterruptedException { - - SMCCHelper smccHelper = new SMCCHelper(); - switch (smccHelper.getResultCode()) { - case SMCCHelper.CARD_FOUND: - System.out.println("card found "); - } - SignatureCard signatureCard = smccHelper.getSignatureCard(new Locale("de")); - Card card = signatureCard.getCard(); - -// SmartCardIO scIO = new SmartCardIO(); -// Map terminalCardMap = scIO.getCards(); -// -// for (CardTerminal ct : terminalCardMap.keySet()) { -// Card card = terminalCardMap.get(ct); -// System.out.println("found card (" + ct.getName() + "): " + Formatter.byteArrayToHexString(card.getATR().getBytes())); - - System.out.println("found card " + Formatter.byteArrayToHexString(card.getATR().getBytes())); - - CardChannel cardchannel; - - //RESET - System.out.println("RESET"); - signatureCard.reset(); - card = signatureCard.getCard(); -// card.disconnect(true); -// card = ct.connect("*"); - - System.out.println("begin exclusive"); - card.beginExclusive(); - System.out.println("get cardchannel"); - cardchannel = card.getBasicChannel(); - - testECard(cardchannel, signatureCard, card); -// testASignPremium(cardchannel, signatureCard, card); - -// } - - } - - public static class TestCard { - - protected CardChannel channel; - protected int ifs_ = 254; - - public TestCard(CardChannel channel) { - this.channel = channel; - } - - protected byte[] readTLVFile(byte[] aid, byte[] ef, String pin, byte kid, int maxLength) - throws SignatureCardException, InterruptedException, CardException { - - - // SELECT FILE (AID) - selectFileAID(aid); - - // SELECT FILE (EF) - ResponseAPDU resp = selectFileFID(ef); - if (resp.getSW() == 0x6a82) { - // EF not found - throw new FileNotFoundException("EF " + toString(ef) + " not found."); - } else if (resp.getSW() != 0x9000) { - throw new SignatureCardException("SELECT FILE with " + "FID=" + toString(ef) + " failed (" + "SW=" + Integer.toHexString(resp.getSW()) + ")."); - } - - // VERIFY - if (pin != null) { - int retries = verifyPIN(pin, kid); - if (retries != -1) { - throw new at.gv.egiz.smcc.VerificationFailedException(retries); - } - } - - return readBinaryTLV(maxLength, (byte) 0x30); - } - - protected byte[] readBinary(CardChannel channel, int offset, int len) - throws CardException, SignatureCardException { - - //transmit(channel,apdu) - ResponseAPDU resp = channel.transmit(new CommandAPDU(0x00, 0xB0, - 0x7F & (offset >> 8), offset & 0xFF, len)); - if (resp.getSW() == 0x9000) { - return resp.getData(); - } else if (resp.getSW() == 0x6982) { - throw new at.gv.egiz.smcc.SecurityStatusNotSatisfiedException(); - } else { - throw new SignatureCardException("Failed to read bytes (" + offset + "+" + len + "): SW=" + Integer.toHexString(resp.getSW())); - } - - } - - protected byte[] readBinaryTLV(int maxSize, byte expectedType) throws CardException, - SignatureCardException { - -// CardChannel channel = getCardChannel(); - - // read first chunk - int len = Math.min(maxSize, ifs_); - byte[] chunk = readBinary(channel, 0, len); - if (chunk.length > 0 && chunk[0] != expectedType) { - return null; - } - int offset = chunk.length; - int actualSize = maxSize; - if (chunk.length > 3) { - if ((chunk[1] & 0x80) > 0) { - int octets = (0x0F & chunk[1]); - actualSize = 2 + octets; - for (int i = 1; i <= octets; i++) { - actualSize += (0xFF & chunk[i + 1]) << ((octets - i) * 8); - } - } else { - actualSize = 2 + chunk[1]; - } - } - ByteBuffer buffer = ByteBuffer.allocate(actualSize); - buffer.put(chunk, 0, Math.min(actualSize, chunk.length)); - while (offset < actualSize) { - len = Math.min(ifs_, actualSize - offset); - chunk = readBinary(channel, offset, len); - buffer.put(chunk); - offset += chunk.length; - } - return buffer.array(); - - } - - protected byte[] selectFileAID(byte[] dfName) throws CardException, SignatureCardException { -// CardChannel channel = getCardChannel(); - ResponseAPDU resp = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x04, - 0x00, dfName, 256)); - if (resp.getSW() != 0x9000) { - throw new SignatureCardException("Failed to select application AID=" + toString(dfName) + ": SW=" + Integer.toHexString(resp.getSW()) + "."); - } else { - return resp.getBytes(); - } - } - - protected ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException { -// CardChannel channel = getCardChannel(); - return channel.transmit(new CommandAPDU(0x00, 0xA4, 0x02, - 0x04, fid, 256)); - } - - protected String toString(byte[] b) { - StringBuffer sb = new StringBuffer(); - if (b != null && b.length > 0) { - sb.append(Integer.toHexString((b[0] & 240) >> 4)); - sb.append(Integer.toHexString(b[0] & 15)); - } - for (int i = 1; i < b.length; i++) { - sb.append(':'); - sb.append(Integer.toHexString((b[i] & 240) >> 4)); - sb.append(Integer.toHexString(b[i] & 15)); - } - return sb.toString(); - } - - protected int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException { - -// CardChannel channel = getCardChannel(); - - ResponseAPDU resp; - if (pin == null) { - // - resp = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, kid)); - } else { - // PIN length in bytes - int len = (int) Math.ceil(pin.length() / 2); - - // BCD encode PIN and marshal PIN block - byte[] pinBytes = new BigInteger(pin, 16).toByteArray(); - byte[] pinBlock = new byte[8]; - if (len < pinBytes.length) { - System.arraycopy(pinBytes, pinBytes.length - len, pinBlock, 1, len); - } else { - System.arraycopy(pinBytes, 0, pinBlock, len - pinBytes.length + 1, - pinBytes.length); - } - pinBlock[0] = (byte) (0x20 + len * 2); - Arrays.fill(pinBlock, len + 1, 8, (byte) 0xff); - - resp = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock));//, false); - - } - - if (resp.getSW() == 0x63c0) { - throw new LockedException("PIN locked."); - } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { - // return number of possible retries - return resp.getSW2() & 0x0f; - } else if (resp.getSW() == 0x6983) { - throw new LockedException(); - } else if (resp.getSW() == 0x6984) { - // PIN LCS = "Initialized" (-> not activated) - throw new NotActivatedException("PIN not set."); - } else if (resp.getSW() == 0x9000) { - return -1; // success - } else { - throw new SignatureCardException("Failed to verify pin: SW=" + Integer.toHexString(resp.getSW())); - } - } - } - - public static class Formatter { - - private static String[] alphabet = {"0", "1", "2", - "3", "4", "5", "6", "7", "8", - "9", "A", "B", "C", "D", "E", - "F"}; - - public static String byteArrayToHexString(byte[] bytes) { - - if (bytes == null || bytes.length <= 0) { - return null; - } - - StringBuffer buf = new StringBuffer(2 * bytes.length); - - byte c = 0x00; - - for (int i = 0; i < bytes.length; i++) { - - // high nibble - c = (byte) (bytes[i] & 0xf0); - - // shift down - c = (byte) (c >>> 4); - - // cut high order bits - c = (byte) (c & 0x0f); - - buf.append(alphabet[(int) c]); - - // low nibble - c = (byte) (bytes[i] & 0x0f); - - buf.append(alphabet[(int) c]); - if (i < bytes.length - 1) { - buf.append(':'); - } - } - - return buf.toString(); - - } - } - - protected void testASignPremium(CardChannel cardchannel, SignatureCard signatureCard, Card card) throws CardException { - byte[] selectMF = new byte[]{(byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x0C, (byte) 0x02, (byte) 0x3F, (byte) 0x00}; - byte[] selectDF_DEC = new byte[] { (byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x0C, (byte) 0x02, (byte) 0xdf, (byte) 0x71 }; - byte[] selectAID_DEC = new byte[] { (byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0xA0, (byte) 0x00, - (byte) 0x00, (byte) 0x01, (byte) 0x18, (byte) 0x45, (byte) 0x4E }; - - CommandAPDU cAPDU; - ResponseAPDU rAPDU; - byte[] sw; - - cAPDU = new CommandAPDU(selectMF); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - - cAPDU = new CommandAPDU(selectAID_DEC); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - - cAPDU = new CommandAPDU(selectDF_DEC); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - - - } - - protected void testECard(CardChannel cardchannel, SignatureCard signatureCard, Card card) throws CardException, InterruptedException, SignatureCardException { -// if (cardTerminal != null) { -// card_ = cardTerminal.connect("*"); -// } - byte[] selectMF = new byte[]{(byte) 0x00, (byte) 0xA4, (byte) 0x00, (byte) 0x0C, (byte) 0x02, (byte) 0x3F, (byte) 0x00}; - byte[] readEF_GDO = new byte[]{(byte) 0x00, (byte) 0xB0, (byte) 0x82, (byte) 0x00, (byte) 0x00}; - CommandAPDU cAPDU; - ResponseAPDU rAPDU; - byte[] sw; - cAPDU = new CommandAPDU(selectMF); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - cAPDU = new CommandAPDU(readEF_GDO); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - byte[] EF_GDO = rAPDU.getData(); - //RESET - System.out.println("RESET"); - signatureCard.reset(); - card = signatureCard.getCard(); -// card.disconnect(true); -// card = ct.connect("*"); - System.out.println("begin exclusive"); - card.beginExclusive(); - System.out.println("get cardchannel"); - cardchannel = card.getBasicChannel(); - byte[] getCLC = new byte[]{(byte) 0x00, (byte) 0xCA, (byte) 0xDF, (byte) 0x20, (byte) 0x00}; - byte[] verifyKartenPIN = new byte[]{(byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x01}; - byte[] selectDF_SichereSignatur = new byte[]{(byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte) 0x08, (byte) 0xD0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x12, (byte) 0x01, (byte) 0x00}; - byte[] verifySignaturPIN = new byte[]{(byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x81}; - cAPDU = new CommandAPDU(getCLC); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - byte[] clc = rAPDU.getData(); - cAPDU = new CommandAPDU(verifyKartenPIN); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - cAPDU = new CommandAPDU(selectDF_SichereSignatur); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - cAPDU = new CommandAPDU(verifySignaturPIN); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - //RESET - System.out.println("RESET"); - signatureCard.reset(); - card = signatureCard.getCard(); - System.out.println("InfoboxReadRequests..."); - PINProvider pinProvider = new PINProvider() { - - @Override - public String providePIN(PINSpec spec, int retries) throws InterruptedException { - if (retries >= 3) { - return "2540"; - } else { - throw new InterruptedException("TOO FEW PIN RETRIES LEFT, ABORTING"); - } - } - }; - byte[] ehic = signatureCard.getInfobox("EHIC", pinProvider, null); - System.out.println("EHIC: " + Formatter.byteArrayToHexString(ehic)); - byte[] grunddaten = signatureCard.getInfobox("Grunddaten", pinProvider, null); - System.out.println("Grunddaten: " + Formatter.byteArrayToHexString(grunddaten)); - //RESET - System.out.println("RESET"); - signatureCard.reset(); - card = signatureCard.getCard(); -// card.disconnect(true); -// card = ct.connect("*"); - System.out.println("begin exclusive"); - card.beginExclusive(); - System.out.println("get cardchannel"); - cardchannel = card.getBasicChannel(); - cAPDU = new CommandAPDU(getCLC); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - assertTrue(Arrays.equals(clc, rAPDU.getData())); - cAPDU = new CommandAPDU(readEF_GDO); - rAPDU = cardchannel.transmit(cAPDU); - sw = new byte[]{(byte) (0xFF & rAPDU.getSW1()), (byte) (0xFF & rAPDU.getSW2())}; - System.out.println("cAPDU: " + Formatter.byteArrayToHexString(cAPDU.getBytes())); - System.out.println("rAPDU (sw=" + Formatter.byteArrayToHexString(sw) + "): " + Formatter.byteArrayToHexString(rAPDU.getData())); - assertTrue(Arrays.equals(EF_GDO, rAPDU.getData())); -// } - } -} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index be5e3fc8..1043b6a1 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -36,6 +36,7 @@ public interface BKUGUIFacade { public static final String ERR_INVALID_HASH = "error.invalid.hash"; public static final String ERR_CARD_LOCKED = "error.card.locked"; public static final String ERR_CARD_NOTACTIVATED = "error.card.notactivated"; + public static final String ERR_PIN_TIMEOUT = "error.pin.timeout"; public static final String ERR_VIEWER = "error.viewer"; public static final String ERR_EXTERNAL_LINK = "error.external.link"; public static final String ERR_CONFIG = "error.config"; @@ -52,6 +53,7 @@ public interface BKUGUIFacade { public static final String TITLE_CARDPIN = "title.cardpin"; public static final String TITLE_SIGN = "title.sign"; public static final String TITLE_ERROR = "title.error"; + public static final String TITLE_ENTRY_TIMEOUT = "title.entry.timeout"; public static final String TITLE_RETRY = "title.retry"; public static final String TITLE_WAIT = "title.wait"; public static final String TITLE_HASHDATA = "title.hashdata"; @@ -60,17 +62,22 @@ public interface BKUGUIFacade { public static final String WINDOWTITLE_OVERWRITE = "windowtitle.overwrite"; public static final String WINDOWTITLE_VIEWER = "windowtitle.viewer"; public static final String WINDOWTITLE_HELP = "windowtitle.help"; - public static final String MESSAGE_WAIT = "message.wait"; - public static final String MESSAGE_INSERTCARD = "message.insertcard"; - public static final String MESSAGE_ENTERPIN = "message.enterpin"; - public static final String MESSAGE_HASHDATALINK = "message.hashdatalink"; - public static final String MESSAGE_HASHDATALINK_TINY = "message.hashdatalink.tiny"; -// public static final String MESSAGE_HASHDATA = "message.hashdata"; - public static final String MESSAGE_HASHDATALIST = "message.hashdatalist"; - public static final String MESSAGE_RETRIES = "message.retries"; - public static final String MESSAGE_LAST_RETRY = "message.retries.last"; - public static final String MESSAGE_OVERWRITE = "message.overwrite"; - public static final String MESSAGE_HELP = "message.help"; + + // removed message.* prefix to reuse keys as help keys + public static final String MESSAGE_WELCOME = "welcome"; + public static final String MESSAGE_WAIT = "wait"; + public static final String MESSAGE_INSERTCARD = "insertcard"; + public static final String MESSAGE_CARD_NOT_SUPPORTED = "cardnotsupported"; + public static final String MESSAGE_ENTERPIN = "enterpin"; + public static final String MESSAGE_ENTERPIN_PINPAD = "enterpin.pinpad"; + public static final String MESSAGE_HASHDATALINK = "hashdatalink"; + public static final String MESSAGE_HASHDATALINK_TINY = "hashdatalink.tiny"; + public static final String MESSAGE_HASHDATALIST = "hashdatalist"; + public static final String MESSAGE_RETRIES = "retries"; + public static final String MESSAGE_LAST_RETRY = "retries.last"; + public static final String MESSAGE_OVERWRITE = "overwrite"; + public static final String MESSAGE_HELP = "help"; + public static final String WARNING_XHTML = "warning.xhtml"; public static final String LABEL_PIN = "label.pin"; public static final String LABEL_PINSIZE = "label.pinsize"; @@ -103,33 +110,48 @@ public interface BKUGUIFacade { */ public Locale getLocale(); - public void showWelcomeDialog(); +// public void showWelcomeDialog(); /** * * @param waitMessage if null, a simple 'please wait' text is displayed */ - public void showWaitDialog(String waitMessage); +// public void showWaitDialog(String waitMessage); + +// public void showInsertCardDialog(ActionListener cancelListener, String actionCommand); - public void showInsertCardDialog(ActionListener cancelListener, String actionCommand); +// public void showCardNotSupportedDialog(ActionListener cancelListener, String actionCommand); - public void showCardNotSupportedDialog(ActionListener cancelListener, String actionCommand); + public void showCardPINDialog(PINSpec pinSpec, int numRetries, + ActionListener okListener, String okCommand, + ActionListener cancelListener, String cancelCommand); - public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); +// public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); - public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); + public void showSignaturePINDialog(PINSpec pinSpec, int numRetries, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); - public void showSignaturePINDialog(PINSpec pinSpec, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); +// public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); - public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); +// public void showPinpadSignaturePINDialog(PINSpec pinSpec, int retries); public char[] getPin(); - public void showHashDataInputDialog(List signedReferences, ActionListener okListener, String okCommand); + public void showSecureViewer(List signedReferences, + ActionListener okListener, String okCommand); - public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, String okCommand); + public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, + ActionListener okListener, String okCommand); public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams); - public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams, ActionListener okListener, String okCommand); + public void showMessageDialog(String titleKey, + String msgKey, Object[] msgParams, + String buttonKey, + ActionListener okListener, String okCommand); + + public void showMessageDialog(String titleKey, + String msgKey, Object[] msgParams); + + public void showMessageDialog(String titleKey, + String msgKey); } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java index 76b1d795..928be249 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -315,200 +315,204 @@ public class BKUGUIImpl implements BKUGUIFacade { return messages.containsKey(key); } - @Override - public void showWelcomeDialog() { - - log.debug("scheduling welcome dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show welcome dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - helpListener.setHelpTopic(HELP_WELCOME); - - JLabel welcomeMsgLabel = new JLabel(); - welcomeMsgLabel.setFont(welcomeMsgLabel.getFont().deriveFont(welcomeMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_WELCOME)); - welcomeMsgLabel.setText(getMessage(MESSAGE_WAIT)); - } else { - welcomeMsgLabel.setText(getMessage(TITLE_WELCOME)); - } - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(welcomeMsgLabel); - GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(welcomeMsgLabel); - if (!renderHeaderPanel) { - messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); - } - - mainPanelLayout.setHorizontalGroup(messageHorizontal); - mainPanelLayout.setVerticalGroup(messageVertical); - - contentPanel.validate(); - - } - }); - } - - @Override - public void showInsertCardDialog(final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling insert card dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show insert card dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_INSERTCARD)); - } - - helpListener.setHelpTopic(HELP_INSERTCARD); - - JLabel insertCardMsgLabel = new JLabel(); - insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(insertCardMsgLabel); - GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup() - .addComponent(insertCardMsgLabel); - - if (!renderHeaderPanel) { - messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); - } - - mainPanelLayout.setHorizontalGroup(messageHorizontal); - mainPanelLayout.setVerticalGroup(messageVertical); - - if (renderCancelButton) { - JButton cancelButton = new JButton(); - cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - cancelButton.setText(getMessage(BUTTON_CANCEL)); - cancelButton.addActionListener(cancelListener); - cancelButton.setActionCommand(cancelCommand); - - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(cancelButton)); - } - - contentPanel.validate(); - } - }); - } +// @Override +// public void showWelcomeDialog() { +// +// log.debug("scheduling welcome dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show welcome dialog"); +// +// mainPanel.removeAll(); +// buttonPanel.removeAll(); +// +// helpListener.setHelpTopic(HELP_WELCOME); +// +// JLabel welcomeMsgLabel = new JLabel(); +// welcomeMsgLabel.setFont(welcomeMsgLabel.getFont().deriveFont(welcomeMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +// +// if (renderHeaderPanel) { +// titleLabel.setText(getMessage(TITLE_WELCOME)); +// welcomeMsgLabel.setText(getMessage(MESSAGE_WAIT)); +// } else { +// welcomeMsgLabel.setText(getMessage(TITLE_WELCOME)); +// } +// +// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +// mainPanel.setLayout(mainPanelLayout); +// +// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() +// .addComponent(welcomeMsgLabel); +// GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +// .addComponent(welcomeMsgLabel); +// if (!renderHeaderPanel) { +// messageHorizontal +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(helpLabel); +// messageVertical +// .addComponent(helpLabel); +// } +// +// mainPanelLayout.setHorizontalGroup(messageHorizontal); +// mainPanelLayout.setVerticalGroup(messageVertical); +// +// contentPanel.validate(); +// +// } +// }); +// } + +// @Override +// public void showInsertCardDialog( +// final ActionListener cancelListener, final String cancelCommand) { +// +// log.debug("scheduling insert card dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show insert card dialog"); +// +// mainPanel.removeAll(); +// buttonPanel.removeAll(); +// +// if (renderHeaderPanel) { +// titleLabel.setText(getMessage(TITLE_INSERTCARD)); +// } +// +// helpListener.setHelpTopic(HELP_INSERTCARD); +// +// JLabel insertCardMsgLabel = new JLabel(); +// insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +// insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); +// +// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +// mainPanel.setLayout(mainPanelLayout); +// +// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() +// .addComponent(insertCardMsgLabel); +// GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup() +// .addComponent(insertCardMsgLabel); +// +// if (!renderHeaderPanel) { +// messageHorizontal +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(helpLabel); +// messageVertical +// .addComponent(helpLabel); +// } +// +// mainPanelLayout.setHorizontalGroup(messageHorizontal); +// mainPanelLayout.setVerticalGroup(messageVertical); +// +// if (renderCancelButton) { +// JButton cancelButton = new JButton(); +// cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +// cancelButton.setText(getMessage(BUTTON_CANCEL)); +// cancelButton.addActionListener(cancelListener); +// cancelButton.setActionCommand(cancelCommand); +// +// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); +// buttonPanel.setLayout(buttonPanelLayout); +// +// buttonPanelLayout.setHorizontalGroup( +// buttonPanelLayout.createSequentialGroup() +// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); +// buttonPanelLayout.setVerticalGroup( +// buttonPanelLayout.createSequentialGroup() +// .addComponent(cancelButton)); +// } +// +// contentPanel.validate(); +// } +// }); +// } /** * only difference to showInsertCard: title text: card not supported * @param cancelListener * @param cancelCommand */ - @Override - public void showCardNotSupportedDialog(final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling card not supported dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show card not supported dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - JLabel insertCardMsgLabel = new JLabel(); - insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); - insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); - } else { - insertCardMsgLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); - } - - helpListener.setHelpTopic(HELP_CARDNOTSUPPORTED); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(insertCardMsgLabel); - GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(insertCardMsgLabel); - if (!renderHeaderPanel) { - messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); - } - - mainPanelLayout.setHorizontalGroup(messageHorizontal); - mainPanelLayout.setVerticalGroup(messageVertical); - - if (renderCancelButton) { - JButton cancelButton = new JButton(); - cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - cancelButton.setText(getMessage(BUTTON_CANCEL)); - cancelButton.addActionListener(cancelListener); - cancelButton.setActionCommand(cancelCommand); - - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createSequentialGroup() - .addComponent(cancelButton)); - } - - contentPanel.validate(); - } - }); - } - - private void showCardPINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener okListener, final String okCommand, final ActionListener cancelListener, final String cancelCommand) { +// @Override +// public void showCardNotSupportedDialog(final ActionListener cancelListener, final String cancelCommand) { +// +// log.debug("scheduling card not supported dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show card not supported dialog"); +// +// mainPanel.removeAll(); +// buttonPanel.removeAll(); +// +// JLabel insertCardMsgLabel = new JLabel(); +// insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +// +// if (renderHeaderPanel) { +// titleLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); +// insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); +// } else { +// insertCardMsgLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); +// } +// +// helpListener.setHelpTopic(HELP_CARDNOTSUPPORTED); +// +// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +// mainPanel.setLayout(mainPanelLayout); +// +// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() +// .addComponent(insertCardMsgLabel); +// GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +// .addComponent(insertCardMsgLabel); +// if (!renderHeaderPanel) { +// messageHorizontal +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(helpLabel); +// messageVertical +// .addComponent(helpLabel); +// } +// +// mainPanelLayout.setHorizontalGroup(messageHorizontal); +// mainPanelLayout.setVerticalGroup(messageVertical); +// +// if (renderCancelButton) { +// JButton cancelButton = new JButton(); +// cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +// cancelButton.setText(getMessage(BUTTON_CANCEL)); +// cancelButton.addActionListener(cancelListener); +// cancelButton.setActionCommand(cancelCommand); +// +// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); +// buttonPanel.setLayout(buttonPanelLayout); +// +// buttonPanelLayout.setHorizontalGroup( +// buttonPanelLayout.createSequentialGroup() +// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); +// buttonPanelLayout.setVerticalGroup( +// buttonPanelLayout.createSequentialGroup() +// .addComponent(cancelButton)); +// } +// +// contentPanel.validate(); +// } +// }); +// } + + @Override + public void showCardPINDialog(final PINSpec pinSpec, final int numRetries, + final ActionListener okListener, final String okCommand, + final ActionListener cancelListener, final String cancelCommand) { log.debug("scheduling card-pin dialog"); @@ -534,7 +538,7 @@ public class BKUGUIImpl implements BKUGUIFacade { JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); okButton.setText(getMessage(BUTTON_OK)); - okButton.setEnabled(false); + okButton.setEnabled(pinSpec.getMinLength() <= 0); okButton.setActionCommand(okCommand); okButton.addActionListener(okListener); @@ -681,27 +685,30 @@ public class BKUGUIImpl implements BKUGUIFacade { }); } - @Override - public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { - showCardPINDialog(pinSpec, -1, okListener, okCommand, cancelListener, cancelCommand); - } - - @Override - public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { - showCardPINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand); - } - - @Override - public void showSignaturePINDialog(PINSpec pinSpec, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand) { - showSignaturePINDialog(pinSpec, -1, signListener, signCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); - } +// @Override +// public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { +// showCardPINDialog(pinSpec, -1, okListener, okCommand, cancelListener, cancelCommand); +// } +// +// @Override +// public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { +// showCardPINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand); +// } + +// @Override +// public void showSignaturePINDialog(PINSpec pinSpec, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand) { +// showSignaturePINDialog(pinSpec, -1, signListener, signCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); +// } @Override - public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand) { - showSignaturePINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); - } - - private void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener signListener, final String signCommand, final ActionListener cancelListener, final String cancelCommand, final ActionListener hashdataListener, final String hashdataCommand) { + public void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, + final ActionListener signListener, final String signCommand, + final ActionListener cancelListener, final String cancelCommand, + final ActionListener hashdataListener, final String hashdataCommand) { +// showSignaturePINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); +// } +// +// private void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener signListener, final String signCommand, final ActionListener cancelListener, final String cancelCommand, final ActionListener hashdataListener, final String hashdataCommand) { log.debug("scheduling signature-pin dialog"); @@ -726,7 +733,7 @@ public class BKUGUIImpl implements BKUGUIFacade { JButton signButton = new JButton(); signButton.setFont(signButton.getFont().deriveFont(signButton.getFont().getStyle() & ~java.awt.Font.BOLD)); signButton.setText(getMessage(BUTTON_SIGN)); - signButton.setEnabled(false); + signButton.setEnabled(pinSpec.getMinLength() <= 0); signButton.setActionCommand(signCommand); signButton.addActionListener(signListener); @@ -888,7 +895,7 @@ public class BKUGUIImpl implements BKUGUIFacade { final ActionListener okListener, final String okCommand) { showMessageDialog(TITLE_ERROR, ERROR_COLOR, - errorMsgKey, errorMsgParams, okListener, okCommand); + errorMsgKey, errorMsgParams, BUTTON_OK, okListener, okCommand); } @Override @@ -896,22 +903,45 @@ public class BKUGUIImpl implements BKUGUIFacade { final String errorMsgKey, final Object[] errorMsgParams) { showMessageDialog(TITLE_ERROR, ERROR_COLOR, - errorMsgKey, errorMsgParams, null, null); + errorMsgKey, errorMsgParams, null, null, null); } @Override public void showMessageDialog( final String titleKey, final String msgKey, final Object[] msgParams, + final String buttonKey, final ActionListener okListener, final String okCommand) { showMessageDialog(titleKey, null, - msgKey, msgParams, okListener, okCommand); + msgKey, msgParams, buttonKey, okListener, okCommand); + } + + @Override + public void showMessageDialog( + final String titleKey, + final String msgKey, final Object[] msgParams) { + + showMessageDialog(titleKey, null, + msgKey, msgParams, null, null, null); + } + + @Override + public void showMessageDialog( + final String titleKey, final String msgKey) { + + showMessageDialog(titleKey, null, + msgKey, null, null, null, null); } + /** + * + * @param buttonKey if null defaults to BUTTON_OK + */ private void showMessageDialog( final String titleKey, final Color titleColor, final String msgKey, final Object[] msgParams, + final String buttonKey, final ActionListener okListener, final String okCommand) { log.debug("scheduling message dialog"); @@ -972,7 +1002,7 @@ public class BKUGUIImpl implements BKUGUIFacade { if (okListener != null) { JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - okButton.setText(getMessage(BUTTON_OK)); + okButton.setText(getMessage((buttonKey != null) ? buttonKey : BUTTON_OK)); okButton.setActionCommand(okCommand); okButton.addActionListener(okListener); @@ -993,57 +1023,57 @@ public class BKUGUIImpl implements BKUGUIFacade { }); } - @Override - public void showWaitDialog(final String waitMessage) { - - log.debug("scheduling wait dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show wait dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_WAIT)); - } - - helpListener.setHelpTopic(HELP_WAIT); - - JLabel waitMsgLabel = new JLabel(); - waitMsgLabel.setFont(waitMsgLabel.getFont().deriveFont(waitMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - if (waitMessage != null) { - waitMsgLabel.setText("" + waitMessage + ""); - } else { - waitMsgLabel.setText(getMessage(MESSAGE_WAIT)); - } - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(waitMsgLabel); - GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(waitMsgLabel); - - if (!renderHeaderPanel) { - messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); - } - mainPanelLayout.setHorizontalGroup(messageHorizontal); - mainPanelLayout.setVerticalGroup(messageVertical); - - contentPanel.validate(); - } - }); - } +// @Override +// public void showWaitDialog(final String waitMessage) { +// +// log.debug("scheduling wait dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show wait dialog"); +// +// mainPanel.removeAll(); +// buttonPanel.removeAll(); +// +// if (renderHeaderPanel) { +// titleLabel.setText(getMessage(TITLE_WAIT)); +// } +// +// helpListener.setHelpTopic(HELP_WAIT); +// +// JLabel waitMsgLabel = new JLabel(); +// waitMsgLabel.setFont(waitMsgLabel.getFont().deriveFont(waitMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +// if (waitMessage != null) { +// waitMsgLabel.setText("" + waitMessage + ""); +// } else { +// waitMsgLabel.setText(getMessage(MESSAGE_WAIT)); +// } +// +// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +// mainPanel.setLayout(mainPanelLayout); +// +// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() +// .addComponent(waitMsgLabel); +// GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +// .addComponent(waitMsgLabel); +// +// if (!renderHeaderPanel) { +// messageHorizontal +// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +// .addComponent(helpLabel); +// messageVertical +// .addComponent(helpLabel); +// } +// mainPanelLayout.setHorizontalGroup(messageHorizontal); +// mainPanelLayout.setVerticalGroup(messageVertical); +// +// contentPanel.validate(); +// } +// }); +// } @Override public char[] getPin() { @@ -1062,7 +1092,7 @@ public class BKUGUIImpl implements BKUGUIFacade { * @param okCommand */ @Override - public void showHashDataInputDialog(final List signedReferences, + public void showSecureViewer(final List signedReferences, final ActionListener okListener, final String okCommand) { diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java index 87b636f0..13aaf870 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java @@ -35,6 +35,7 @@ class PINDocument extends PlainDocument { protected Pattern pinPattern; protected JButton enterButton; protected Document compareTo; + protected Document oldPin; public PINDocument(PINSpec pinSpec, JButton enterButton) { this.pinSpec = pinSpec; @@ -46,11 +47,30 @@ class PINDocument extends PlainDocument { this.enterButton = enterButton; } + /** + * + * @param pinSpec + * @param enterButton + * @param compareTo enable enterButton iff this pinDocument's pin equals to compareTo's pin. may be null + */ public PINDocument(PINSpec pinSpec, JButton enterButton, Document compareTo) { this(pinSpec, enterButton); this.compareTo = compareTo; } + /** + * + * @param pinSpec + * @param enterButton may be null + * @param compareTo enable enterButton iff this pinDocument's pin equals to compareTo's pin. may be null + * @param oldPin enable enterButton iff oldPin meets the pinSpec pin length requirements, may be null + */ + public PINDocument(PINSpec pinSpec, JButton enterButton, Document compareTo, Document oldPin) { + this(pinSpec, enterButton); + this.compareTo = compareTo; + this.oldPin = oldPin; + } + @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { if (pinSpec.getMaxLength() < 0 || pinSpec.getMaxLength() >= (getLength() + str.length())) { @@ -66,7 +86,10 @@ class PINDocument extends PlainDocument { } } if (enterButton != null) { - enterButton.setEnabled(getLength() >= pinSpec.getMinLength() && compare()); + enterButton.setEnabled( + (oldPin == null || oldPin.getLength() >= pinSpec.getMinLength()) && + getLength() >= pinSpec.getMinLength() && + compare()); } } @@ -74,7 +97,10 @@ class PINDocument extends PlainDocument { public void remove(int offs, int len) throws BadLocationException { super.remove(offs, len); if (enterButton != null) { - enterButton.setEnabled(getLength() >= pinSpec.getMinLength() && compare()); + enterButton.setEnabled( + (oldPin == null || oldPin.getLength() >= pinSpec.getMinLength()) && + getLength() >= pinSpec.getMinLength() && + compare()); } } diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 1e0bc9f5..6d651b2d 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -20,6 +20,7 @@ title.cardnotsupported=Die Karte wird nicht unterst\u00FCtzt title.cardpin=Karte wird gelesen title.sign=Signatur erstellen title.error=Fehler +title.entry.timeout=Zeit\u00FCberschreitung title.retry=Falsche PIN title.wait=Bitte warten title.hashdata=Signaturdaten @@ -28,19 +29,25 @@ windowtitle.savedir=Signaturdaten in Verzeichnis speichern windowtitle.overwrite=Datei \u00FCberschreiben? windowtitle.viewer=Signaturdaten windowtitle.help=Hilfe zur B\u00FCrgerkarte -message.wait=Bitte warten... -message.insertcard=Bitte die B\u00FCrgerkarte in den Kartenleser stecken -message.enterpin={0} eingeben -message.hashdatalink=Signaturdaten anzeigen -message.hashdatalink.tiny=Signaturdaten + +# removed message.* prefix to reuse keys as help keys +welcome=Bitte warten... +wait=Bitte warten... +cardnotsupported=Bitte die B\u00FCrgerkarte in den Kartenleser stecken +insertcard=Bitte die B\u00FCrgerkarte in den Kartenleser stecken +enterpin={0} eingeben +enterpin.pinpad={0} ({1} stellig) am Kartenleser eingeben +hashdatalink=Signaturdaten anzeigen +hashdatalink.tiny=Signaturdaten #message.hashdata=Hinweis: Dies ist eine Voransicht des zu signierenden Inhalts. F\u00FCr eine standardkonforme Darstellung siehe Hilfe (i). #message.hashdata=Dies ist eine Voransicht des zu signierenden Inhaltes. F\u00FCr Details siehe Hilfe (i). #verwenden sie bitte die von ihrem System zur Verf\u00FCgung gestellte {0} Anwendung. -message.hashdatalist={0} Signaturdaten: -message.retries.last=Letzter Versuch! -message.retries=Noch {0} Versuche -message.overwrite=M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben? -message.help=Hilfe zu {0} +hashdatalist={0} Signaturdaten: +retries.last=Letzter Versuch! +retries=Noch {0} Versuche +overwrite=M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben? +help=Hilfe zu {0} + warning.xhtml=Hinweis: Dies ist eine Voransicht des zu signierenden Inhalts. F\u00FCr eine standardkonforme Darstellung siehe Hilfe (i). label.pin={0}: label.pinsize=({0} stellig) @@ -73,6 +80,7 @@ error.unknown=Ein Fehler trat auf error.test=Fehler1 {0} - Fehler2 {1} error.card.locked=B\u00FCrgerkarte ist gesperrt error.card.notactivated=B\u00FCrgerkartenfunktion ist nicht aktiviert +error.pin.timeout=Zeit\u00FCberschreitung bei Eingabe der PIN error.viewer=Der Inhalt kann nicht dargestellt werden: {0} error.external.link=Externer Link {0} wird nicht ge\u00F6ffnet error.config=Fehlerhafte Konfiguration des Systems: {0} diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties index 4fbccd5b..2fb66969 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties @@ -20,6 +20,7 @@ title.cardnotsupported=This card is not supported title.cardpin=Reading card title.sign=Create signature title.error=Error +title.entry.timeout=Timeout title.retry=Wrong PIN title.wait=Please wait title.hashdata=Signature data @@ -28,17 +29,23 @@ windowtitle.savedir=Save signature data to directory windowtitle.overwrite=Overwrite file? windowtitle.viewer=Signature data windowtitle.help=Citizen card help -message.wait=Please wait... -message.insertcard=Please insert your citizen card into the reader -message.enterpin=Enter {0} -message.hashdatalink=Display signature data -message.hashdatalink.tiny=signature data + +# removed message.* prefix to reuse keys as help keys +welcome=Please wait... +wait=Please wait... +insertcard=Please insert your citizen card into the reader +cardnotsupported=Please insert your citizen card into the reader +enterpin=Enter {0} +enterpin.pinpad=Enter {0} ({1} digits) on card reader pinpad +hashdatalink=Display signature data +hashdatalink.tiny=signature data #message.hashdata=Remark: This is a preview of the data to-be signed. For standards compliant display see help. -message.hashdatalist={0} signature data objects: -message.retries.last=Last try! -message.retries={0} tries left -message.overwrite=Overwrite {0}? -message.help=Help topic {0} +hashdatalist={0} signature data objects: +retries.last=Last try! +retries={0} tries left +overwrite=Overwrite {0}? +help=Help topic {0} + warning.xhtml=Remark: This is a preview of the data to-be signed. For standards compliant display see help. label.pin={0}: label.pinsize=({0} digits) @@ -71,6 +78,7 @@ error.unknown=An error occured error.test=Error1 {0} - Error2 {1} error.card.locked=Citizen card is locked error.card.notactivated=Citizen card not activated +error.pin.timeout=Timeout during PIN entry error.viewer=Failed to display contents: {0} error.external.link=Cannot open external link {0} error.config=Incorrect system configuration: {0} diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index ef64ac59..194e18b0 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -78,7 +78,7 @@ public class BKUGUIWorker implements Runnable { @Override public void actionPerformed(ActionEvent e) { - gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", null, "hashdata"); + gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", null, "hashdata"); } }; HashDataInput signedRef1 = new ByteArrayHashDataInput( @@ -116,7 +116,7 @@ public class BKUGUIWorker implements Runnable { // signedRefs.add(signedRef4); // signedRefs.add(signedRef4); // signedRefs = Collections.singletonList(signedRef1); - gui.showHashDataInputDialog(signedRefs, returnListener, "return"); + gui.showSecureViewer(signedRefs, returnListener, "return"); } }; @@ -149,7 +149,7 @@ public class BKUGUIWorker implements Runnable { // // Thread.sleep(2000); // - gui.showSignaturePINDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); + gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); // // Thread.sleep(4000); // diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java index 1714017e..5a0ba84a 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java @@ -40,27 +40,27 @@ public class BKUGuiProxy implements BKUGUIFacade { return delegate.getLocale(); } +// @Override +// public void showCardNotSupportedDialog(ActionListener cancelListener, +// String actionCommand) { +// showDialog(); +// delegate.showCardNotSupportedDialog(cancelListener, actionCommand); +// } +// +// @Override +// public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, +// String okCommand, ActionListener cancelListener, String cancelCommand) { +// showDialog(); +// delegate.showCardPINDialog(pinSpec, okListener, okCommand, cancelListener, +// cancelCommand); +// } +// @Override - public void showCardNotSupportedDialog(ActionListener cancelListener, - String actionCommand) { - showDialog(); - delegate.showCardNotSupportedDialog(cancelListener, actionCommand); - } - - @Override - public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, - String okCommand, ActionListener cancelListener, String cancelCommand) { - showDialog(); - delegate.showCardPINDialog(pinSpec, okListener, okCommand, cancelListener, - cancelCommand); - } - - @Override - public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, + public void showCardPINDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { showDialog(); - delegate.showCardPINRetryDialog(pinSpec, numRetries, okListener, okCommand, + delegate.showCardPINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand); } @@ -77,57 +77,71 @@ public class BKUGuiProxy implements BKUGUIFacade { delegate.showErrorDialog(errorMsgKey, errorMsgParams); } +// @Override +// public void showInsertCardDialog(ActionListener cancelListener, +// String actionCommand) { +// showDialog(); +// delegate.showInsertCardDialog(cancelListener, actionCommand); +// } +// +// @Override +// public void showSignaturePINDialog(PINSpec pinSpec, +// ActionListener signListener, String signCommand, +// ActionListener cancelListener, String cancelCommand, +// ActionListener hashdataListener, String hashdataCommand) { +// showDialog(); +// delegate.showSignaturePINDialog(pinSpec, signListener, signCommand, +// cancelListener, cancelCommand, hashdataListener, hashdataCommand); +// } +// @Override - public void showInsertCardDialog(ActionListener cancelListener, - String actionCommand) { - showDialog(); - delegate.showInsertCardDialog(cancelListener, actionCommand); - } - - @Override - public void showSignaturePINDialog(PINSpec pinSpec, - ActionListener signListener, String signCommand, - ActionListener cancelListener, String cancelCommand, - ActionListener hashdataListener, String hashdataCommand) { - showDialog(); - delegate.showSignaturePINDialog(pinSpec, signListener, signCommand, - cancelListener, cancelCommand, hashdataListener, hashdataCommand); - } - - @Override - public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries, + public void showSignaturePINDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand) { showDialog(); - delegate.showSignaturePINRetryDialog(pinSpec, numRetries, okListener, + delegate.showSignaturePINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); } +// +// @Override +// public void showWaitDialog(String waitMessage) { +// showDialog(); +// delegate.showWaitDialog(waitMessage); +// } +// +// @Override +// public void showWelcomeDialog() { +// showDialog(); +// delegate.showWelcomeDialog(); +// } @Override - public void showWaitDialog(String waitMessage) { + public void showSecureViewer(List signedReferences, + ActionListener okListener, + String okCommand) { showDialog(); - delegate.showWaitDialog(waitMessage); + delegate.showSecureViewer(signedReferences, okListener, okCommand); } @Override - public void showWelcomeDialog() { + public void showMessageDialog(String titleKey, + String msgKey, Object[] msgParams, + String buttonKey, ActionListener okListener, String okCommand) { showDialog(); - delegate.showWelcomeDialog(); + delegate.showMessageDialog(titleKey, msgKey, msgParams, buttonKey, okListener, okCommand); } @Override - public void showHashDataInputDialog(List signedReferences, - ActionListener okListener, - String okCommand) { + public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams) { showDialog(); - delegate.showHashDataInputDialog(signedReferences, okListener, okCommand); + delegate.showMessageDialog(titleKey, msgKey, msgParams); } @Override - public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams, ActionListener okListener, String okCommand) { + public void showMessageDialog(String titleKey, String msgKey) { showDialog(); - delegate.showMessageDialog(titleKey, msgKey, msgParams, okListener, okCommand); + delegate.showMessageDialog(titleKey, msgKey); } } diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java index 46f915a9..531e6591 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java @@ -67,7 +67,7 @@ public class LocalSignRequestHandler extends SignRequestHandler { * @throws java.lang.Exception */ @Override - public void displayHashDataInputs(List dsigReferences) throws Exception { + public void displayDataToBeSigned(List dsigReferences) throws Exception { if (dsigReferences == null || dsigReferences.size() < 1) { log.error("No hashdata input selected to be displayed: null"); throw new Exception("No HashData Input selected to be displayed"); @@ -109,7 +109,7 @@ public class LocalSignRequestHandler extends SignRequestHandler { log.error("dsig:SignedInfo does not contain a data reference"); throw new Exception("dsig:SignedInfo does not contain a data reference"); } - gui.showHashDataInputDialog(selectedHashDataInputs, this, "hashDataDone"); + gui.showSecureViewer(selectedHashDataInputs, this, "hashDataDone"); } private ByteArrayHashDataInput getByteArrayHashDataInput(HashDataInput hashDataInput) throws IOException { diff --git a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java index d15d2c1b..833dbf4d 100644 --- a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java +++ b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java @@ -1,10 +1,5 @@ package at.gv.egiz.bku.local.app; -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.mortbay.jetty.Connector; diff --git a/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.html b/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.html new file mode 100644 index 00000000..021ddfa7 --- /dev/null +++ b/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.html @@ -0,0 +1,47 @@ + + + + +Untitled Document + + + + + + +
+ +
+

Bildschirmfoto des Applets

+

Hinweis: Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.

+
+
+

Die Karte wird nicht unterstützt

+

Die im Kartenleser gesteckte Chipkarte wird nicht unterstützt.

+

Bitte stecken Sie eine unterstützte Chipkarte (Bürgerkarte) in den Kartenleser. Derzeit werden die folgenden Chipkarten unterstützt:

+ +

Sind mehrere unterstützte Kartenleser angeschlossen, stecken sie eine unterstützte Chipkarte (Bürgerkarte) in einen der angeschlossenen Kartenleser. Wird die Chipkarte erkannt wechselt die Bildschirmanzeige. Wird die Chipkarte nicht erkannt, wird der Kartenleser möglicherweise nicht unterstützt. Stecken Sie die Chipkarte daher in einen anderen Kartenleser.

+


+
+ +
+ + diff --git a/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.png b/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.png new file mode 100644 index 00000000..c3b7ce6b Binary files /dev/null and b/BKUOnline/src/main/webapp/helpfiles/de/cardnotsupported.png differ diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.html b/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.html deleted file mode 100644 index c647bf72..00000000 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -Untitled Document - - - - - - -
- -
-

Bildschirmfoto des Applets

-

Hinweis: Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.

-
-
-

Die Karte wird nicht unterstützt

-

Die im Kartenleser gesteckte Chipkarte wird nicht unterstützt.

-

Bitte stecken Sie eine unterstützte Chipkarte (Bürgerkarte) in den Kartenleser. Derzeit werden die folgenden Chipkarten unterstützt:

- -

Sind mehrere unterstützte Kartenleser angeschlossen, stecken sie eine unterstützte Chipkarte (Bürgerkarte) in einen der angeschlossenen Kartenleser. Wird die Chipkarte erkannt wechselt die Bildschirmanzeige. Wird die Chipkarte nicht erkannt, wird der Kartenleser möglicherweise nicht unterstützt. Stecken Sie die Chipkarte daher in einen anderen Kartenleser.

-


-
- -
- - diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.png b/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.png deleted file mode 100644 index c3b7ce6b..00000000 Binary files a/BKUOnline/src/main/webapp/helpfiles/de/help.cardnotsupported.png and /dev/null differ diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.html b/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.html deleted file mode 100644 index 0bfc6230..00000000 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - -Untitled Document - - - - - - -
- -
-

Bildschirmfoto des Applets

-

Hinweis: Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.

-
-
-

Bitte die Bürgerkarte in den Kartenleser stecken

-

Die Software für den Zugriff auf die Bürgerkarte hat einen oder mehrere unterstützte Kartenleser gefunden.

-

Bitte stecken Sie nun ihre Bürgerkarte in den Kartenleser. Wird die Karte erkannt, welchselt die Bildschirmanzeige.

-

Sollten Sie mehrere Kartenleser angeschlossen haben, wählen Sie einen beliebigen aus. Wird die Karte im ausgewählten Kartenleser nicht erkannt, wird dieser Kartenleser eventuell nicht unterstützt. Probieren Sie es daher in einem anderen Kartenleser nochmal. -

-


-
- -
- - diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.png b/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.png deleted file mode 100644 index 62a22975..00000000 Binary files a/BKUOnline/src/main/webapp/helpfiles/de/help.insertcard.png and /dev/null differ diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.wait.html b/BKUOnline/src/main/webapp/helpfiles/de/help.wait.html deleted file mode 100644 index ed3db1b8..00000000 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.wait.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - -Untitled Document - - - - - - -
- -
-

Bildschirmfoto des Applets

-

Hinweis: Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.

-
-
-

Bitte warten ...

-

Die Software für den Zugriff auf die Bürgerkarte ist damit beschäftigt, einen Befehl auszuführen bzw. auf einen neuen Befehl vom Server zu warten.

-


-
- -
- - diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.wait.png b/BKUOnline/src/main/webapp/helpfiles/de/help.wait.png deleted file mode 100644 index 63a38fbf..00000000 Binary files a/BKUOnline/src/main/webapp/helpfiles/de/help.wait.png and /dev/null differ diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.html b/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.html deleted file mode 100644 index 9796a206..00000000 --- a/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - -Untitled Document - - - - - - -
- -
-

Bildschirmfoto des Applets

-

Hinweis: Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.

-
-
-

Willkommen

-

Die Anzeige "Willkommen" erfolgt unmittelbar nachdem die Software für den Zugriff auf die Bürgerkarte erfolgreich im Browser geladen wurde.

-

Die Software versucht nun eine Verbindung mit dem Server aufzunehmen um Befehle für den Zugriff auf die Bürgerkarte zu erhalten.

-


-
- -
- - diff --git a/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.png b/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.png deleted file mode 100644 index 78133b4d..00000000 Binary files a/BKUOnline/src/main/webapp/helpfiles/de/help.welcome.png and /dev/null differ diff --git a/BKUOnline/src/main/webapp/helpfiles/de/insertcard.html b/BKUOnline/src/main/webapp/helpfiles/de/insertcard.html new file mode 100644 index 00000000..f7f1a28a --- /dev/null +++ b/BKUOnline/src/main/webapp/helpfiles/de/insertcard.html @@ -0,0 +1,42 @@ + + + + +Untitled Document + + + + + + +
+ +
+

Bildschirmfoto des Applets

+

Hinweis: Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.

+
+
+

Bitte die Bürgerkarte in den Kartenleser stecken

+

Die Software für den Zugriff auf die Bürgerkarte hat einen oder mehrere unterstützte Kartenleser gefunden.

+

Bitte stecken Sie nun ihre Bürgerkarte in den Kartenleser. Wird die Karte erkannt, welchselt die Bildschirmanzeige.

+

Sollten Sie mehrere Kartenleser angeschlossen haben, wählen Sie einen beliebigen aus. Wird die Karte im ausgewählten Kartenleser nicht erkannt, wird dieser Kartenleser eventuell nicht unterstützt. Probieren Sie es daher in einem anderen Kartenleser nochmal. +

+


+
+ +
+ + diff --git a/BKUOnline/src/main/webapp/helpfiles/de/insertcard.png b/BKUOnline/src/main/webapp/helpfiles/de/insertcard.png new file mode 100644 index 00000000..62a22975 Binary files /dev/null and b/BKUOnline/src/main/webapp/helpfiles/de/insertcard.png differ diff --git a/BKUOnline/src/main/webapp/helpfiles/de/wait.html b/BKUOnline/src/main/webapp/helpfiles/de/wait.html new file mode 100644 index 00000000..8561ff35 --- /dev/null +++ b/BKUOnline/src/main/webapp/helpfiles/de/wait.html @@ -0,0 +1,39 @@ + + + + +Untitled Document + + + + + + +
+ +
+

Bildschirmfoto des Applets

+

Hinweis: Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.

+
+
+

Bitte warten ...

+

Die Software für den Zugriff auf die Bürgerkarte ist damit beschäftigt, einen Befehl auszuführen bzw. auf einen neuen Befehl vom Server zu warten.

+


+
+ +
+ + diff --git a/BKUOnline/src/main/webapp/helpfiles/de/wait.png b/BKUOnline/src/main/webapp/helpfiles/de/wait.png new file mode 100644 index 00000000..63a38fbf Binary files /dev/null and b/BKUOnline/src/main/webapp/helpfiles/de/wait.png differ diff --git a/BKUOnline/src/main/webapp/helpfiles/de/welcome.html b/BKUOnline/src/main/webapp/helpfiles/de/welcome.html new file mode 100644 index 00000000..6c5463e5 --- /dev/null +++ b/BKUOnline/src/main/webapp/helpfiles/de/welcome.html @@ -0,0 +1,40 @@ + + + + +Untitled Document + + + + + + +
+ +
+

Bildschirmfoto des Applets

+

Hinweis: Das Bildschirmfoto oben kann von der Darstellung in der Webseite abweichen.

+
+
+

Willkommen

+

Die Anzeige "Willkommen" erfolgt unmittelbar nachdem die Software für den Zugriff auf die Bürgerkarte erfolgreich im Browser geladen wurde.

+

Die Software versucht nun eine Verbindung mit dem Server aufzunehmen um Befehle für den Zugriff auf die Bürgerkarte zu erhalten.

+


+
+ +
+ + diff --git a/BKUOnline/src/main/webapp/helpfiles/de/welcome.png b/BKUOnline/src/main/webapp/helpfiles/de/welcome.png new file mode 100644 index 00000000..78133b4d Binary files /dev/null and b/BKUOnline/src/main/webapp/helpfiles/de/welcome.png differ diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOS04Card.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOS04Card.java new file mode 100644 index 00000000..9fca6ab9 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOS04Card.java @@ -0,0 +1,30 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc; + +/** + * + * @author Clemens Orthacker + */ +public class ACOS04Card extends ACOSCard { + + public ACOS04Card() { + pinSpecs.remove(PINSPEC_INF); + } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java index c2c62fd8..01b9155b 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -29,9 +29,10 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.util.SMCCHelper; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; import java.nio.charset.Charset; -import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -100,9 +101,9 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { (byte) 0x01 // RSA // TODO: Not verified yet }; - private static final int PINSPEC_INF = 0; - private static final int PINSPEC_DEC = 1; - private static final int PINSPEC_SIG = 2; + protected static final int PINSPEC_INF = 0; + protected static final int PINSPEC_DEC = 1; + protected static final int PINSPEC_SIG = 2; public ACOSCard() { super("at/gv/egiz/smcc/ACOSCard"); @@ -179,15 +180,12 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name")); int retries = -1; - String pin = null; + char[] pin = null; boolean pinRequiered = false; do { if (pinRequiered) { pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } } try { getCard().beginExclusive(); @@ -234,20 +232,17 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { //new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); int retries = -1; - String pin = null; + char[] pin = null; do { pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } try { getCard().beginExclusive(); // SELECT DF selectFileFID(DF_SIG); // VERIFY - retries = verifyPIN(pin, KID_PIN_SIG); + retries = verifyPIN(KID_PIN_SIG, pin); if (retries != -1) { throw new VerificationFailedException(retries); } @@ -259,7 +254,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { return psoComputDigitalSiganture(); } catch (SecurityStatusNotSatisfiedException e) { - retries = verifyPIN(null, KID_PIN_SIG); + retries = verifyPIN(KID_PIN_SIG); } catch (VerificationFailedException e) { retries = e.getRetries(); } finally { @@ -276,15 +271,12 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name")); int retries = -1; - String pin = null; - boolean pinRequiered = false; + char[] pin = null; + boolean pinRequired = false; do { - if (pinRequiered) { + if (pinRequired) { pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } } try { getCard().beginExclusive(); @@ -292,7 +284,7 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { // SELECT DF selectFileFID(DF_DEC); // VERIFY - retries = verifyPIN(pin, KID_PIN_DEC); + retries = verifyPIN(KID_PIN_DEC, pin); if (retries != -1) { throw new VerificationFailedException(retries); } @@ -304,10 +296,10 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } catch (FileNotFoundException e) { throw new NotActivatedException(); } catch (SecurityStatusNotSatisfiedException e) { - pinRequiered = true; - retries = verifyPIN(null, KID_PIN_DEC); + pinRequired = true; + retries = verifyPIN(KID_PIN_DEC); } catch (VerificationFailedException e) { - pinRequiered = true; + pinRequired = true; retries = e.getRetries(); } finally { getCard().endExclusive(); @@ -328,48 +320,16 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } + //////////////////////////////////////////////////////////////////////// + // PROTECTED METHODS (assume exclusive card access) + //////////////////////////////////////////////////////////////////////// + protected ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); return transmit(channel, new CommandAPDU(0x00, 0xA4, 0x00, 0x00, fid, 256)); } - @Override - protected int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { - - CardChannel channel = getCardChannel(); - - ResponseAPDU resp; - try { - if (pin != null) { - resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, encodePINBlock(pin)), false); - } else { - //TODO this is not supported - resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid), false); - } - } catch (CardException ex) { - log.error("smart card communication failed: " + ex.getMessage()); - throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); - } - - //6A 00 (falshe P1/P2) nicht in contextAID - //69 85 (nutzungsbedingungen nicht erfüllt) in DF_Sig und nicht sigpin - - if (resp.getSW() == 0x63c0) { - throw new LockedException("PIN locked."); - } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { - // return number of possible retries - return resp.getSW2() & 0x0f; - } else if (resp.getSW() == 0x6983) { - throw new NotActivatedException(); - } else if (resp.getSW() == 0x9000) { - return -1; - } else { - throw new SignatureCardException("Failed to verify pin: SW=" - + Integer.toHexString(resp.getSW()) + "."); - } - } - private void mseSetDST(int p1, int p2, byte[] dst) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0x22, p1, @@ -426,92 +386,294 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } } - @Override - public String toString() { - return "a-sign premium"; - } - /** - * ASCII encoded pin, padded with 0x00 - * @param pin - * @return a 8 byte pin block + * + * @param kid + * @return -1 */ - private byte[] encodePINBlock(String pin) { - byte[] asciiPIN = pin.getBytes(Charset.forName("ASCII")); - byte[] encodedPIN = new byte[8]; - System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, - encodedPIN.length)); -// System.out.println("ASCII encoded PIN block: " + SMCCHelper.toString(encodedPIN)); - return encodedPIN; + @Override + protected int verifyPIN(byte kid) { + log.debug("VERIFY PIN without PIN BLOCK not supported by ACOS"); + return -1; } @Override - public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { - throw new SignatureCardException("PIN activation not supported by this card"); + protected int verifyPIN(byte kid, char[] pin) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException { + try { + byte[] sw; + if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { + log.debug("verify PIN on IFD"); + sw = transmitControlCommand( + ifdCtrlCmds.get(FEATURE_VERIFY_PIN_DIRECT), + getPINVerifyStructure(kid)); +// int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; + } else { + byte[] pinBlock = encodePINBlock(pin); + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock), false); + sw = new byte[2]; + sw[0] = (byte) resp.getSW1(); + sw[1] = (byte) resp.getSW2(); + } + + //6A 00 (falshe P1/P2) nicht in contextAID + //69 85 (nutzungsbedingungen nicht erfüllt) in DF_Sig und nicht sigpin + + if (sw[0] == (byte) 0x90 && sw[1] == (byte) 0x00) { + return -1; + } else if (sw[0] == (byte) 0x63 && sw[1] == (byte) 0xc0) { + throw new LockedException("[63:c0]"); + } else if (sw[0] == (byte) 0x63 && (sw[1] & 0xf0) >> 4 == 0xc) { + return sw[1] & 0x0f; + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x83) { + //Authentisierungsmethode gesperrt + throw new NotActivatedException("[69:83]"); +// } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x84) { +// //referenzierte Daten sind reversibel gesperrt (invalidated) +// throw new NotActivatedException("[69:84]"); +// } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x85) { +// //Benutzungsbedingungen nicht erfüllt +// throw new NotActivatedException("[69:85]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x00) { + throw new TimeoutException("[64:00]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { + throw new CancelledException("[64:01]"); + } + log.error("Failed to verify pin: SW=" + + SMCCHelper.toString(sw)); + throw new SignatureCardException(SMCCHelper.toString(sw)); + + } catch (CardException ex) { + log.error("smart card communication failed: " + ex.getMessage()); + throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); + } } /** * SCARD_E_NOT_TRANSACTED inf/dec PIN not active (pcsc crash) - * @param pinSpec - * @param oldPIN - * @param newPIN + * @param kid + * @param oldPin + * @param newPin + * @return * @throws at.gv.egiz.smcc.LockedException - * @throws at.gv.egiz.smcc.VerificationFailedException * @throws at.gv.egiz.smcc.NotActivatedException * @throws at.gv.egiz.smcc.SignatureCardException */ @Override - public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) - throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { - Card icc = getCard(); + protected int changePIN(byte kid, char[] oldPin, char[] newPin) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException { try { - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); - - if (pinSpec.getContextAID() != null) { - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + - ": SW=" + Integer.toHexString(responseAPDU.getSW()); - log.error(msg); - throw new SignatureCardException(msg); - } - } - - byte[] cmd = new byte[16]; - System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); - System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); + byte[] sw; + if (ifdSupportsFeature(FEATURE_MODIFY_PIN_DIRECT)) { + log.debug("modify PIN on IFD"); + sw = transmitControlCommand( + ifdCtrlCmds.get(FEATURE_MODIFY_PIN_DIRECT), + getPINModifyStructure(kid)); +// int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; + } else { + byte[] cmd = new byte[16]; + System.arraycopy(encodePINBlock(oldPin), 0, cmd, 0, 8); + System.arraycopy(encodePINBlock(newPin), 0, cmd, 8, 8); - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0x24, 0x00, pinSpec.getKID(), cmd), false); + CardChannel channel = getCardChannel(); - icc.endExclusive(); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x00, kid, cmd), false); - log.debug("change pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + sw = new byte[2]; + sw[0] = (byte) resp.getSW1(); + sw[1] = (byte) resp.getSW2(); + } - if (responseAPDU.getSW() == 0x63c0) { - log.error(pinSpec.getLocalizedName() + " locked"); - throw new LockedException(); - } else if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { - int retries = responseAPDU.getSW2() & 0x0f; - log.error("wrong " + pinSpec.getLocalizedName() + ", " + retries + " retries"); - throw new VerificationFailedException(retries); - } else if (responseAPDU.getSW() == 0x6983) { + // activates pin (newPIN) if not active + if (sw[0] == (byte) 0x90 && sw[1] == (byte) 0x00) { + return -1; + } else if (sw[0] == (byte) 0x63 && sw[1] == (byte) 0xc0) { + throw new LockedException("[63:c0]"); + } else if (sw[0] == (byte) 0x63 && (sw[1] & 0xf0) >> 4 == 0xc) { + return sw[1] & 0x0f; + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x83) { + //Authentisierungsmethode gesperrt // sig-pin only (card not transacted for inf/dec pin) - log.error(pinSpec.getLocalizedName() + " not activated"); - throw new NotActivatedException(); - } else if (responseAPDU.getSW() != 0x9000) { - String msg = "Failed to change " + pinSpec.getLocalizedName() + - ": SW=" + Integer.toHexString(responseAPDU.getSW()); - log.error(msg); - throw new SignatureCardException(msg); + throw new NotActivatedException("[69:83]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x00) { + throw new TimeoutException("[64:00]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { + throw new CancelledException("[64:01]"); } + log.error("Failed to change pin: SW=" + + SMCCHelper.toString(sw)); + throw new SignatureCardException(SMCCHelper.toString(sw)); + } catch (CardException ex) { - log.error("Failed to change " + pinSpec.getLocalizedName() + - ": " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); + log.error("smart card communication failed: " + ex.getMessage()); + throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); } } + + /** + * throws SignatureCardException (PIN activation not supported by ACOS) + * @throws at.gv.egiz.smcc.SignatureCardException + */ + @Override + public void activatePIN(byte kid, char[] pin) + throws SignatureCardException { + log.error("ACTIVATE PIN not supported by ACOS"); + throw new SignatureCardException("PIN activation not supported by this card"); + } + + /** + * ASCII encoded pin, padded with 0x00 + * @param pin + * @return a 8 byte pin block + */ + @Override + protected byte[] encodePINBlock(char[] pin) { +// byte[] asciiPIN = new String(pin).getBytes(Charset.forName("ASCII")); + CharBuffer chars = CharBuffer.wrap(pin); + ByteBuffer bytes = Charset.forName("ASCII").encode(chars); + byte[] asciiPIN = bytes.array(); + byte[] encodedPIN = new byte[8]; + System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, + encodedPIN.length)); +// System.out.println("ASCII encoded PIN block: " + SMCCHelper.toString(encodedPIN)); + return encodedPIN; + } + + private byte[] getPINVerifyStructure(byte kid) { + + byte bTimeOut = (byte) 00; // Default time out + byte bTimeOut2 = (byte) 00; // Default time out + byte bmFormatString = (byte) 0x82; // 1 0001 0 01 + // ^------------ System unit = byte + // ^^^^------- PIN position in the frame = 1 byte + // ^----- PIN justification left + // ^^-- BCD format + // 1 0000 0 10 + // ^^-- ASCII format + byte bmPINBlockString = (byte) 0x08; // 0100 0111 + // ^^^^--------- PIN length size: 4 bits + // ^^^^---- Length PIN = 7 bytes + byte bmPINLengthFormat = (byte) 0x04; // 000 0 0100 + // ^-------- System bit units is bit + // ^^^^--- PIN length is at the 4th position bit + byte wPINMaxExtraDigitL = (byte) 0x04; // Max=4 digits + byte wPINMaxExtraDigitH = (byte) 0x04; // Min=4 digits + byte bEntryValidationCondition = 0x02; // Max size reach or Validation key pressed + byte bNumberMessage = (byte) 0x00; // No message + byte wLangIdL = (byte) 0x0C; // - English? + byte wLangIdH = (byte) 0x04; // \ + byte bMsgIndex = (byte) 0x00; // Default Msg + + byte[] apdu = new byte[] { + (byte) 0x00, (byte) 0x20, (byte) 0x00, kid, (byte) 0x08, // CLA INS P1 P2 LC + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // Data + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 // Data + }; + + int offset = 0; + byte[] pinVerifyStructure = new byte[offset + 19 + apdu.length]; + pinVerifyStructure[offset++] = bTimeOut; + pinVerifyStructure[offset++] = bTimeOut2; + pinVerifyStructure[offset++] = bmFormatString; + pinVerifyStructure[offset++] = bmPINBlockString; + pinVerifyStructure[offset++] = bmPINLengthFormat; + pinVerifyStructure[offset++] = wPINMaxExtraDigitL; + pinVerifyStructure[offset++] = wPINMaxExtraDigitH; + pinVerifyStructure[offset++] = bEntryValidationCondition; + pinVerifyStructure[offset++] = bNumberMessage; + pinVerifyStructure[offset++] = wLangIdL; + pinVerifyStructure[offset++] = wLangIdH; + pinVerifyStructure[offset++] = bMsgIndex; + + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + + pinVerifyStructure[offset++] = (byte) apdu.length; + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + System.arraycopy(apdu, 0, pinVerifyStructure, offset, apdu.length); + + return pinVerifyStructure; + } + + public byte[] getPINModifyStructure(byte kid) { + + byte bTimeOut = (byte) 00; // Default time out + byte bTimeOut2 = (byte) 00; // Default time out + byte bmFormatString = (byte) 0x82; // 1 0001 0 01 + // ^------------ System unit = byte + // ^^^^------- PIN position in the frame = 1 byte + // ^----- PIN justification left + // ^^-- BCD format + // 1 0000 0 10 + // ^^-- ASCII format + byte bmPINBlockString = (byte) 0x08; // 0100 0111 + // ^^^^--------- PIN length size: 4 bits + // ^^^^---- Length PIN = 7 bytes + byte bmPINLengthFormat = (byte) 0x00; // 000 0 0100 + // ^-------- System bit units is bit + // ^^^^--- PIN length is at the 4th position bit + byte bInsertionOffsetOld = (byte) 0x00; // insertion position offset in bytes + byte bInsertionOffsetNew = (byte) 0x00; // insertion position offset in bytes + byte wPINMaxExtraDigitL = (byte) 0x04; // Min=4 digits + byte wPINMaxExtraDigitH = (byte) 0x04; // Max=12 digits + byte bConfirmPIN = (byte) 0x00; // ??? need for confirm pin + byte bEntryValidationCondition = 0x02; // Max size reach or Validation key pressed + byte bNumberMessage = (byte) 0x00; // No message + byte wLangIdL = (byte) 0x0C; // - English? + byte wLangIdH = (byte) 0x04; // \ + byte bMsgIndex1 = (byte) 0x00; // Default Msg + byte bMsgIndex2 = (byte) 0x00; // Default Msg + byte bMsgIndex3 = (byte) 0x00; // Default Msg + + byte[] apdu = new byte[] { + (byte) 0x00, (byte) 0x24, (byte) 0x00, kid, (byte) 0x10, // CLA INS P1 P2 LC + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, // Data + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, // ... + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, // Data + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff // ... + }; + + int offset = 0; + byte[] pinModifyStructure = new byte[offset + 24 + apdu.length]; + pinModifyStructure[offset++] = bTimeOut; + pinModifyStructure[offset++] = bTimeOut2; + pinModifyStructure[offset++] = bmFormatString; + pinModifyStructure[offset++] = bmPINBlockString; + pinModifyStructure[offset++] = bmPINLengthFormat; + pinModifyStructure[offset++] = bInsertionOffsetOld; + pinModifyStructure[offset++] = bInsertionOffsetNew; + pinModifyStructure[offset++] = wPINMaxExtraDigitL; + pinModifyStructure[offset++] = wPINMaxExtraDigitH; + pinModifyStructure[offset++] = bConfirmPIN; + pinModifyStructure[offset++] = bEntryValidationCondition; + pinModifyStructure[offset++] = bNumberMessage; + pinModifyStructure[offset++] = wLangIdL; + pinModifyStructure[offset++] = wLangIdH; + pinModifyStructure[offset++] = bMsgIndex1; + pinModifyStructure[offset++] = bMsgIndex2; + pinModifyStructure[offset++] = bMsgIndex3; + + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + + pinModifyStructure[offset++] = (byte) apdu.length; + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + System.arraycopy(apdu, 0, pinModifyStructure, offset, apdu.length); + + return pinModifyStructure; + } + + @Override + public String toString() { + return "a-sign premium"; + } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java index 39952bb9..6587aaf9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -33,12 +33,12 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.ResourceBundle; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; @@ -54,6 +54,14 @@ public abstract class AbstractSignatureCard implements SignatureCard { private static Log log = LogFactory.getLog(AbstractSignatureCard.class); + static final short GET_FEATURE_REQUEST = 3400; + + private static int getCtrlCode(short function) { + return 0x310000 | ((0xFFFF & function) << 2); + } + + protected Map ifdCtrlCmds; + protected List pinSpecs = new ArrayList(); private ResourceBundle i18n; @@ -106,11 +114,14 @@ public abstract class AbstractSignatureCard implements SignatureCard { */ protected byte[] selectFileAID(byte[] dfName) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x04, - 0x00, dfName, 256)); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0xA4, 0x04, 0x00, dfName, 256)); +// new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, dfName)); if (resp.getSW() != 0x9000) { - throw new SignatureCardException("Failed to select application AID=" - + toString(dfName) + ": SW=" + Integer.toHexString(resp.getSW()) + "."); + String msg = "Failed to select application AID=" + SMCCHelper.toString(dfName) + + ": SW=" + Integer.toHexString(resp.getSW()); + log.error(msg); + throw new SignatureCardException(msg); } else { return resp.getBytes(); } @@ -119,10 +130,63 @@ public abstract class AbstractSignatureCard implements SignatureCard { protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException; - protected abstract int verifyPIN(String pin, byte kid) + /** + * VERIFY APDU without PIN BLOCK + * Not supported by ACOS cards (and GemPC Pinpad?) + * @param kid + * @return the number of possible tries until card is blocked or -1 if unknown + * (ACOS does not support this VERIFY APDU type) + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + protected abstract int verifyPIN(byte kid) throws LockedException, NotActivatedException, SignatureCardException; - + /** + * VERIFY APDU with PIN BLOCK + * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. + * @param kid + * @param pin to be encoded in the PIN BLOCK + * @return -1 if VERIFY PIN was successful, or the number of possible retries + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + protected abstract int verifyPIN(byte kid, char[] pin) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException; + + /** + * CHANGE(?) APDU + * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. + * @param kid + * @param pin + * @throws at.gv.egiz.smcc.SignatureCardException if activation fails + */ + protected abstract void activatePIN(byte kid, char[] pin) + throws CancelledException, TimeoutException, SignatureCardException; + + /** + * CHANGE(?) APDU + * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. + * @param kid + * @param pin + * @return -1 if CHANGE PIN was successful, or the number of possible retries + * @throws at.gv.egiz.smcc.SignatureCardException if change fails + */ + protected abstract int changePIN(byte kid, char[] oldPin, char[] newPin) + throws CancelledException, TimeoutException, SignatureCardException; + + /** + * encode the pin as needed in VERIFY/CHANGE APDUs + * @param pin + * @return + * @throws at.gv.egiz.smcc.SignatureCardException if the provided pin does + * not meet the restrictions imposed by the encoding (not the pinSpec!), + * such as maximum Length + */ + protected abstract byte[] encodePINBlock(char[] pin) throws SignatureCardException; + protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { return readRecord(getCardChannel(), recordNumber); } @@ -295,7 +359,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws SignatureCardException * @throws CardException */ - protected byte[] readTLVFile(byte[] aid, byte[] ef, String pin, byte kid, int maxLength) + protected byte[] readTLVFile(byte[] aid, byte[] ef, char[] pin, byte kid, int maxLength) throws SignatureCardException, InterruptedException, CardException { @@ -318,7 +382,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { // VERIFY if (pin != null) { - int retries = verifyPIN(pin, kid); + int retries = verifyPIN(kid, pin); if (retries != -1) { throw new VerificationFailedException(retries); } @@ -388,6 +452,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { ifs_ = 0xFF & atr.getBytes()[6]; log.trace("Setting IFS (information field size) to " + ifs_); } + ifdCtrlCmds = queryIFDFeatures(); } @Override @@ -446,39 +511,266 @@ public abstract class AbstractSignatureCard implements SignatureCard { } @Override - public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { - - Card icc = getCard(); + public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { try { - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); + getCard().beginExclusive(); if (pinSpec.getContextAID() != null) { - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Failed to verify PIN " + - SMCCHelper.toString(new byte[]{pinSpec.getKID()}) + - ": Failed to verify AID " + - SMCCHelper.toString(pinSpec.getContextAID()) + - ": " + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); - } + selectFileAID(pinSpec.getContextAID()); } - return verifyPIN(pin, pinSpec.getKID()); + + int retries = verifyPIN(pinSpec.getKID()); + do { + char[] pin = pinProvider.providePIN(pinSpec, retries); + retries = verifyPIN(pinSpec.getKID(), pin); + } while (retries > 0); + //return on -1, 0 never reached: verifyPIN throws LockedEx } catch (CardException ex) { - log.error("failed to verify pinspec: " + ex.getMessage(), ex); + log.error("failed to verify " + pinSpec.getLocalizedName() + + ": " + ex.getMessage(), ex); throw new SignatureCardException(ex); } finally { try { - icc.endExclusive(); + getCard().endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); + } + } + } + + @Override + public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) + throws CancelledException, SignatureCardException, CancelledException, TimeoutException, InterruptedException { + try { + getCard().beginExclusive(); + + if (pinSpec.getContextAID() != null) { + selectFileAID(pinSpec.getContextAID()); + } + char[] pin = pinProvider.providePIN(pinSpec, -1); + activatePIN(pinSpec.getKID(), pin); + + } catch (CardException ex) { + log.error("Failed to activate " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } finally { + try { + getCard().endExclusive(); } catch (CardException ex) { log.trace("failed to end exclusive card access: " + ex.getMessage()); } + } + } + + /** + * activates pin (newPIN) if not active + * @param pinSpec + * @param oldPIN + * @param newPIN + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.VerificationFailedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + @Override + public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { + try { + getCard().beginExclusive(); + + if (pinSpec.getContextAID() != null) { + selectFileAID(pinSpec.getContextAID()); + } + + int retries = verifyPIN(pinSpec.getKID()); + do { + char[] newPin = pinProvider.providePIN(pinSpec, retries); + char[] oldPin = pinProvider.provideOldPIN(pinSpec, retries); + retries = changePIN(pinSpec.getKID(), oldPin, newPin); + } while (retries > 0); + //return on -1, 0 never reached: verifyPIN throws LockedEx + } catch (CardException ex) { + log.error("Failed to change " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } finally { + try { + getCard().endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); + } } } + + @Override + public void unblockPIN(PINSpec pinSpec, PINProvider pinProvider) + throws CancelledException, SignatureCardException, InterruptedException { + throw new SignatureCardException("Unblock not supported yet"); + } + + ///////////////////////////////////////////////////////////////////////////// + // IFD related code + ///////////////////////////////////////////////////////////////////////////// + + /** + * TODO implement VERIFY_PIN_START/FINISH (feature 0x01/0x02) + * @return + */ + @Override + public boolean ifdSupportsFeature(byte feature) { + if (ifdCtrlCmds != null) { + return ifdCtrlCmds.containsKey(feature); + } + return false; + } + + protected Map queryIFDFeatures() { + + if (card_ == null) { + throw new NullPointerException("Need connected smart card to query IFD features"); + } + + Map ifdFeatures = new HashMap(); + + try { + if (log.isTraceEnabled()) { + log.trace("GET_FEATURE_REQUEST CtrlCode " + Integer.toHexString(getCtrlCode(GET_FEATURE_REQUEST))); + } + byte[] resp = card_.transmitControlCommand(getCtrlCode(GET_FEATURE_REQUEST), new byte[]{}); + + if (log.isTraceEnabled()) { + log.trace("GET_FEATURE_REQUEST Response " + SMCCHelper.toString(resp)); + } + + for (int i = 0; i + 5 < resp.length; i += 6) { + Byte feature = new Byte(resp[i]); + Long ctrlCode = new Long( + ((0xFF & resp[i + 2]) << 24) | + ((0xFF & resp[i + 3]) << 16) | + ((0xFF & resp[i + 4]) << 8) | + (0xFF & resp[i + 5])); + if (log.isInfoEnabled()) { + log.info("IFD supports feature " + Integer.toHexString(feature.byteValue()) + + ": " + Long.toHexString(ctrlCode.longValue())); + } + ifdFeatures.put(feature, ctrlCode); + } + + } catch (CardException ex) { + log.debug("Failed to query IFD features: " + ex.getMessage()); + log.trace(ex); + log.info("IFD does not support PINPad"); + return null; + } + return ifdFeatures; + } + + + protected byte ifdGetKeyPressed() throws CardException { + if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { + + Long controlCode = (Long) ifdCtrlCmds.get(new Byte((byte) 0x05)); + + byte key = 0x00; + while (key == 0x00) { + + byte[] resp = card_.transmitControlCommand(controlCode.intValue(), new byte[] {}); + + if (resp != null && resp.length > 0) { + key = resp[0]; + } + } + + System.out.println("Key: " + key); + + } + + return 0x00; + } + + protected byte[] ifdVerifyPINFinish() throws CardException { + if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { + + Long controlCode = (Long) ifdCtrlCmds.get(new Byte((byte) 0x02)); + + byte[] resp = card_.transmitControlCommand(controlCode.intValue(), new byte[] {}); + + System.out.println("CommandResp: " + toString(resp)); + + return resp; + + } + + return null; + } + + + /** + * assumes ifdSupportsVerifyPIN() == true + * @param pinVerifyStructure + * @return + * @throws javax.smartcardio.CardException + */ +// protected byte[] ifdVerifyPIN(byte[] pinVerifyStructure) throws CardException { +// +//// Long ctrlCode = (Long) ifdFeatures.get(FEATURE_IFD_PIN_PROPERTIES); +//// if (ctrlCode != null) { +//// if (log.isTraceEnabled()) { +//// log.trace("PIN_PROPERTIES CtrlCode " + Integer.toHexString(ctrlCode.intValue())); +//// } +//// byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), new byte[] {}); +//// +//// if (log.isTraceEnabled()) { +//// log.trace("PIN_PROPERTIES Response " + SMCCHelper.toString(resp)); +//// } +//// } +// +// +// Long ctrlCode = (Long) ifdFeatures.get(FEATURE_VERIFY_PIN_DIRECT); +// if (ctrlCode == null) { +// throw new NullPointerException("no CtrlCode for FEATURE_VERIFY_PIN_DIRECT"); +// } +// +// if (log.isTraceEnabled()) { +// log.trace("VERIFY_PIN_DIRECT CtrlCode " + Integer.toHexString(ctrlCode.intValue()) + +// ", PIN_VERIFY_STRUCTURE " + SMCCHelper.toString(pinVerifyStructure)); +// } +// byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), pinVerifyStructure); +// +// if (log.isTraceEnabled()) { +// log.trace("VERIFY_PIN_DIRECT Response " + SMCCHelper.toString(resp)); +// } +// return resp; +// } + +// protected Long getControlCode(Byte feature) { +// if (ifdFeatures != null) { +// return ifdFeatures.get(feature); +// } +// return null; +// } + + protected byte[] transmitControlCommand(Long ctrlCode, byte[] ctrlCommand) + throws CardException { +// Long ctrlCode = (Long) ifdFeatures.get(feature); + if (ctrlCode == null) { + throw new NullPointerException("ControlCode " + + Integer.toHexString(ctrlCode.intValue()) + " not supported"); + } + if (log.isTraceEnabled()) { + log.trace("CtrlCommand (" + Integer.toHexString(ctrlCode.intValue()) + + ") " + SMCCHelper.toString(ctrlCommand)); + } + byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), ctrlCommand); + + if (log.isTraceEnabled()) { + log.trace("CtrlCommand Response " + SMCCHelper.toString(resp)); + } + return resp; + } + } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java new file mode 100644 index 00000000..d0622aa4 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java @@ -0,0 +1,39 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc; + +import at.gv.egiz.smcc.*; + +/** + * + * @author Clemens Orthacker + */ +public interface ChangePINProvider extends PINProvider { + + /** + * + * @param spec + * @param retries + * @return null if no old value for this pin + * @throws at.gv.egiz.smcc.CancelledException if cancelled by user + * @throws java.lang.InterruptedException + */ + public char[] provideOldPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException; + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java index e0104618..8fa80dcb 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java @@ -28,8 +28,30 @@ // package at.gv.egiz.smcc; +/** + * The number of retries is not fixed and there is no way (?) to obtain this value. + * A PINProvider should therefore maintain an internal retry counter or flag + * to decide whether or not to warn the user (num retries passed in providePIN). + * + * Therefore PINProvider objects should not be reused. + * + * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated) + * + * @author Clemens Orthacker + */ public interface PINProvider { - - public String providePIN(PINSpec spec, int retries) throws InterruptedException; + + /** + * + * @param spec + * @param retries num of remaining retries or -1 if unknown + * (a positive value does not necessarily signify that there was + * already an unsuccessful PIN verification) + * @return pin != null + * @throws at.gv.egiz.smcc.CancelledException + * @throws java.lang.InterruptedException + */ + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException; } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java index 3c5f38a2..91245c50 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -30,7 +30,6 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.util.SMCCHelper; import java.util.Arrays; -import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -223,15 +222,12 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); int retries = -1; - String pin = null; + char[] pin = null; boolean pinRequiered = false; do { if (pinRequiered) { pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } } try { getCard().beginExclusive(); @@ -240,7 +236,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard throw new NotActivatedException(); } catch (SecurityStatusNotSatisfiedException e) { pinRequiered = true; - retries = verifyPIN(null, KID_PIN_CARD); + retries = verifyPIN(KID_PIN_CARD); } catch (VerificationFailedException e) { pinRequiered = true; retries = e.getRetries(); @@ -316,20 +312,17 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard //new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); int retries = -1; - String pin = null; + char[] pin = null; do { try { getCard().beginExclusive(); selectFileAID(AID_DF_SS); - retries = verifyPIN(null, KID_PIN_SS); + retries = verifyPIN(KID_PIN_SS); //, null); } finally { getCard().endExclusive(); } pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } try { getCard().beginExclusive(); return createSignature(hash, AID_DF_SS, pin, KID_PIN_SS, DST_SS); @@ -349,15 +342,12 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); int retries = -1; - String pin = null; + char[] pin = null; boolean pinRequiered = false; do { if (pinRequiered) { pin = provider.providePIN(spec, retries); - if (pin == null) { - throw new CancelledException(); - } } try { getCard().beginExclusive(); @@ -366,7 +356,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard throw new NotActivatedException(); } catch (SecurityStatusNotSatisfiedException e) { pinRequiered = true; - retries = verifyPIN(null, KID_PIN_CARD); + retries = verifyPIN(KID_PIN_CARD); } catch (VerificationFailedException e) { pinRequiered = true; retries = e.getRetries(); @@ -389,13 +379,18 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } + + //////////////////////////////////////////////////////////////////////// + // PROTECTED METHODS (assume exclusive card access) + //////////////////////////////////////////////////////////////////////// + protected ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); return transmit(channel, new CommandAPDU(0x00, 0xA4, 0x02, 0x04, fid, 256)); } - private byte[] createSignature(byte[] hash, byte[] aid, String pin, byte kid, + private byte[] createSignature(byte[] hash, byte[] aid, char[] pin, byte kid, byte[] dst) throws CardException, SignatureCardException { // SELECT MF @@ -403,7 +398,7 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard // SELECT DF selectFileAID(aid); // VERIFY - int retries = verifyPIN(pin, kid); + int retries = verifyPIN(kid, pin); if (retries != -1) { throw new VerificationFailedException(retries); } @@ -417,7 +412,6 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } - private void selectMF() throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x00, @@ -467,58 +461,85 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } } - /** - * VERIFY PIN - *

- * If pin is null only the PIN status is checked and - * returned. - *

- * - * @param pin - * the PIN (may be null) - * @param kid - * the KID of the PIN to be verified - * - * @return -1 if VERIFY PIN was successful, or the number of possible retries - * - * @throws LockedException - * if the pin is locked - * @throws NotActivatedException - * if the card application has not been activated - * @throws SignatureCardException - * if VERIFY PIN fails for some other reason (card communication error) - */ @Override - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { + protected int verifyPIN(byte kid, char[] pin) + throws LockedException, NotActivatedException, SignatureCardException { try { - CardChannel channel = getCardChannel(); - - ResponseAPDU resp; - if (pin == null) { - resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid)); + byte[] sw; + if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { + log.debug("verify PIN on IFD"); + sw = transmitControlCommand( + ifdCtrlCmds.get(FEATURE_VERIFY_PIN_DIRECT), + getPINVerifyStructure(kid)); +// int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; } else { - // BCD encode PIN and marshal PIN block byte[] pinBlock = encodePINBlock(pin); - resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock), false); + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock), false); + sw = new byte[2]; + sw[0] = (byte) resp.getSW1(); + sw[1] = (byte) resp.getSW2(); + } + if (sw[0] == (byte) 0x90 && sw[1] == (byte) 0x00) { + return -1; + } else if (sw[0] == (byte) 0x63 && sw[1] == (byte) 0xc0) { + throw new LockedException("[63:c0]"); + } else if (sw[0] == (byte) 0x63 && (sw[1] & 0xf0) >> 4 == 0xc) { + return sw[1] & 0x0f; + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x83) { + //Authentisierungsmethode gesperrt + throw new LockedException("[69:83]"); + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x84) { + //referenzierte Daten sind reversibel gesperrt (invalidated) + throw new NotActivatedException("[69:84]"); + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x85) { + //Benutzungsbedingungen nicht erfüllt + throw new NotActivatedException("[69:85]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x00) { + throw new TimeoutException("[64:00]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { + throw new CancelledException("[64:01]"); } + log.error("Failed to verify pin: SW=" + + SMCCHelper.toString(sw)); + throw new SignatureCardException(SMCCHelper.toString(sw)); + + } catch (CardException ex) { + log.error("smart card communication failed: " + ex.getMessage()); + throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); + } + } - if (resp.getSW() == 0x63c0) { - throw new LockedException("PIN locked."); - } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { - // return number of possible retries + @Override + protected int verifyPIN(byte kid) + throws LockedException, NotActivatedException, SignatureCardException { + try { + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x20, 0x00, kid), false); + + if (resp.getSW() == 0x9000) { + return -1; + } else if (resp.getSW() == 0x63c0) { + throw new LockedException("[63:c0]"); + } else if (resp.getSW1() == 0x63 && (resp.getSW2() & 0xf0) >> 4 == 0xc) { return resp.getSW2() & 0x0f; } else if (resp.getSW() == 0x6983) { - throw new LockedException(); + //Authentisierungsmethode gesperrt + throw new LockedException("[69:83]"); } else if (resp.getSW() == 0x6984) { - // PIN LCS = "Initialized" (-> not activated) - throw new NotActivatedException(); - } else if (resp.getSW() == 0x9000) { - return -1; // success - } else { - throw new SignatureCardException("Failed to verify pin: SW=" - + Integer.toHexString(resp.getSW())); + //referenzierte Daten sind reversibel gesperrt (invalidated) + throw new NotActivatedException("[69:84]"); + } else if (resp.getSW() == 0x6985) { + //Benutzungsbedingungen nicht erfüllt + throw new NotActivatedException("[69:85]"); } + log.error("Failed to verify pin: SW=" + + Integer.toHexString(resp.getSW())); + throw new SignatureCardException("[" + Integer.toHexString(resp.getSW()) + "]"); + } catch (CardException ex) { log.error("smart card communication failed: " + ex.getMessage()); throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); @@ -526,24 +547,95 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } @Override - public void reset() throws SignatureCardException { + protected int changePIN(byte kid, char[] oldPin, char[] newPin) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException { try { - super.reset(); - log.debug("select MF (e-card workaround)"); - CardChannel channel = getCardChannel(); - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x00, 0x0C)); - if (resp.getSW() != 0x9000) { - throw new SignatureCardException("Failed to select MF after RESET: SW=" + Integer.toHexString(resp.getSW()) + "."); + byte[] sw; + if (ifdSupportsFeature(FEATURE_MODIFY_PIN_DIRECT)) { + log.debug("modify PIN on IFD"); + sw = transmitControlCommand( + ifdCtrlCmds.get(FEATURE_MODIFY_PIN_DIRECT), + getPINModifyStructure(kid)); +// int sw = (resp[resp.length-2] & 0xff) << 8 | resp[resp.length-1] & 0xff; + } else { + byte[] cmd = new byte[16]; + System.arraycopy(encodePINBlock(oldPin), 0, cmd, 0, 8); + System.arraycopy(encodePINBlock(newPin), 0, cmd, 8, 8); + + CardChannel channel = getCardChannel(); + + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x00, kid, cmd), false); + + sw = new byte[2]; + sw[0] = (byte) resp.getSW1(); + sw[1] = (byte) resp.getSW2(); + } + + // activates pin (newPIN) if not active + if (sw[0] == (byte) 0x90 && sw[1] == (byte) 0x00) { + return -1; + } else if (sw[0] == (byte) 0x63 && sw[1] == (byte) 0xc0) { + throw new LockedException("[63:c0]"); + } else if (sw[0] == (byte) 0x63 && (sw[1] & 0xf0) >> 4 == 0xc) { + return sw[1] & 0x0f; + } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x83) { + //Authentisierungsmethode gesperrt + throw new LockedException("[69:83]"); +// } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x84) { +// //referenzierte Daten sind reversibel gesperrt (invalidated) +// throw new NotActivatedException("[69:84]"); +// } else if (sw[0] == (byte) 0x69 && sw[1] == (byte) 0x85) { +// //Benutzungsbedingungen nicht erfüllt +// throw new NotActivatedException("[69:85]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x00) { + throw new TimeoutException("[64:00]"); + } else if (sw[0] == (byte) 0x64 && sw[1] == (byte) 0x01) { + throw new CancelledException("[64:01]"); } + log.error("Failed to change pin: SW=" + + SMCCHelper.toString(sw)); + throw new SignatureCardException(SMCCHelper.toString(sw)); } catch (CardException ex) { - log.error("Failed to select MF after RESET: " + ex.getMessage(), ex); - throw new SignatureCardException("Failed to select MF after RESET"); + log.error("smart card communication failed: " + ex.getMessage()); + throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); } } + @Override + protected void activatePIN(byte kid, char[] pin) + throws CancelledException, TimeoutException, SignatureCardException { + try { + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0x24, 0x01, kid, encodePINBlock(pin)), false); + + log.trace("activate pin returned SW=" + Integer.toHexString(resp.getSW())); - public String toString() { - return "e-card"; + if (resp.getSW1() == 0x9000) { + return; + } else if (resp.getSW() == 0x6983) { + //Authentisierungsmethode gesperrt + throw new LockedException("[69:83]"); + } else if (resp.getSW() == 0x6984) { + //referenzierte Daten sind reversibel gesperrt (invalidated) + throw new NotActivatedException("[69:84]"); + } else if (resp.getSW() == 0x6985) { + //Benutzungsbedingungen nicht erfüllt + throw new NotActivatedException("[69:85]"); + } else if (resp.getSW() == 0x6400) { + throw new TimeoutException("[64:00]"); + } else if (resp.getSW() == 0x6401) { + throw new CancelledException("[64:01]"); + } + log.error("Failed to activate pin: SW=" + + Integer.toHexString(resp.getSW())); + throw new SignatureCardException("[" + Integer.toHexString(resp.getSW()) + "]"); + + } catch (CardException ex) { + log.error("smart card communication failed: " + ex.getMessage()); + throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); + } } /** @@ -552,17 +644,20 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard * @return a 8 byte pin block consisting of length byte (0x2X), * the BCD encoded pin and a 0xFF padding */ - private byte[] encodePINBlock(String pin) { - char[] pinChars = pin.toCharArray(); - int numDigits = pinChars.length; + @Override + protected byte[] encodePINBlock(char[] pin) throws SignatureCardException { + if (pin == null || pin.length > 12) { + throw new SignatureCardException("invalid pin: " + pin); + } + int numDigits = pin.length; int numBytes = (int) Math.ceil(numDigits/2.0); byte[] pinBlock = new byte[8]; pinBlock[0] = (byte) (0x20 | numDigits); for (int i = 0; i < numBytes; i++) { - int p1 = 16*Character.digit(pinChars[i*2], 16); - int p2 = (i*2+1 < numDigits) ? Character.digit(pinChars[i*2+1], 16) : 0xf; + int p1 = 16*Character.digit(pin[i*2], 16); + int p2 = (i*2+1 < numDigits) ? Character.digit(pin[i*2+1], 16) : 0xf; pinBlock[i+1] = (byte) (p1 + p2); } Arrays.fill(pinBlock, numBytes + 1, pinBlock.length, (byte) 0xff); @@ -570,111 +665,151 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard return pinBlock; } + + private byte[] getPINVerifyStructure(byte kid) { + + byte bTimeOut = (byte) 00; // Default time out + byte bTimeOut2 = (byte) 00; // Default time out + byte bmFormatString = (byte) 0x89; // 1 0001 0 01 + // ^------------ System unit = byte + // ^^^^------- PIN position in the frame = 1 byte + // ^----- PIN justification left + // ^^-- BCD format + byte bmPINBlockString = (byte) 0x47; // 0100 0111 + // ^^^^--------- PIN length size: 4 bits + // ^^^^---- Length PIN = 7 bytes + byte bmPINLengthFormat = (byte) 0x04; // 000 0 0100 + // ^-------- System bit units is bit + // ^^^^--- PIN length is at the 4th position bit + byte wPINMaxExtraDigitL = (byte) 0x04; // Max=4 digits + byte wPINMaxExtraDigitH = (byte) 0x04; // Min=4 digits + byte bEntryValidationCondition = 0x02; // Max size reach or Validation key pressed + byte bNumberMessage = (byte) 0x00; // No message + byte wLangIdL = (byte) 0x0C; // - English? + byte wLangIdH = (byte) 0x04; // \ + byte bMsgIndex = (byte) 0x00; // Default Msg + + byte[] apdu = new byte[] { + (byte) 0x00, (byte) 0x20, (byte) 0x00, kid, (byte) 0x08, // CLA INS P1 P2 LC + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, // Data + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff // ... + }; + + int offset = 0; + byte[] pinVerifyStructure = new byte[offset + 19 + apdu.length]; + pinVerifyStructure[offset++] = bTimeOut; + pinVerifyStructure[offset++] = bTimeOut2; + pinVerifyStructure[offset++] = bmFormatString; + pinVerifyStructure[offset++] = bmPINBlockString; + pinVerifyStructure[offset++] = bmPINLengthFormat; + pinVerifyStructure[offset++] = wPINMaxExtraDigitL; + pinVerifyStructure[offset++] = wPINMaxExtraDigitH; + pinVerifyStructure[offset++] = bEntryValidationCondition; + pinVerifyStructure[offset++] = bNumberMessage; + pinVerifyStructure[offset++] = wLangIdL; + pinVerifyStructure[offset++] = wLangIdH; + pinVerifyStructure[offset++] = bMsgIndex; + + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + + pinVerifyStructure[offset++] = (byte) apdu.length; + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + pinVerifyStructure[offset++] = 0x00; + System.arraycopy(apdu, 0, pinVerifyStructure, offset, apdu.length); - @Override - public void activatePIN(PINSpec pinSpec, String pin) - throws SignatureCardException { - Card icc = getCard(); - try { - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); - - if (pinSpec.getContextAID() != null) { - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + - ": SW=" + Integer.toHexString(responseAPDU.getSW()); - log.error(msg); - throw new SignatureCardException(msg); - } - } - - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0x24, 0x01, pinSpec.getKID(), encodePINBlock(pin)), - false); - - icc.endExclusive(); - - log.debug("activate pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); + return pinVerifyStructure; + } - if (responseAPDU.getSW() != 0x9000) { - String msg = "Failed to activate " + pinSpec.getLocalizedName() + - ": SW=" + Integer.toHexString(responseAPDU.getSW()); - log.error(msg); - throw new SignatureCardException(msg); - } - } catch (CardException ex) { - log.error("Failed to activate " + pinSpec.getLocalizedName() + - ": " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); - } + private byte[] getPINModifyStructure(byte kid) { + + byte bTimeOut = (byte) 00; // Default time out + byte bTimeOut2 = (byte) 00; // Default time out + byte bmFormatString = (byte) 0x89; // 1 0001 0 01 + // ^------------ System unit = byte + // ^^^^------- PIN position in the frame = 1 byte + // ^----- PIN justification left + // ^^-- BCD format + byte bmPINBlockString = (byte) 0x47; // 0100 0111 + // ^^^^--------- PIN length size: 4 bits + // ^^^^---- Length PIN = 7 bytes + byte bmPINLengthFormat = (byte) 0x04; // 000 0 0100 + // ^-------- System bit units is bit + // ^^^^--- PIN length is at the 4th position bit + byte bInsertionOffsetOld = (byte) 0x01; // insertion position offset in bytes + byte bInsertionOffsetNew = (byte) 0x08; // insertion position offset in bytes + byte wPINMaxExtraDigitL = (byte) 0x04; // Min=4 digits + byte wPINMaxExtraDigitH = (byte) 0x04; // Max=12 digits + byte bConfirmPIN = (byte) 0x00; // ??? need for confirm pin + byte bEntryValidationCondition = 0x02; // Max size reach or Validation key pressed + byte bNumberMessage = (byte) 0x00; // No message + byte wLangIdL = (byte) 0x0C; // - English? + byte wLangIdH = (byte) 0x04; // \ + byte bMsgIndex1 = (byte) 0x00; // Default Msg + byte bMsgIndex2 = (byte) 0x00; // Default Msg + byte bMsgIndex3 = (byte) 0x00; // Default Msg + + byte[] apdu = new byte[] { + (byte) 0x00, (byte) 0x24, (byte) 0x00, kid, (byte) 0x10, // CLA INS P1 P2 LC + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, // Data + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, // ... + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, // Data + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff // ... + }; + + int offset = 0; + byte[] pinModifyStructure = new byte[offset + 24 + apdu.length]; + pinModifyStructure[offset++] = bTimeOut; + pinModifyStructure[offset++] = bTimeOut2; + pinModifyStructure[offset++] = bmFormatString; + pinModifyStructure[offset++] = bmPINBlockString; + pinModifyStructure[offset++] = bmPINLengthFormat; + pinModifyStructure[offset++] = bInsertionOffsetOld; + pinModifyStructure[offset++] = bInsertionOffsetNew; + pinModifyStructure[offset++] = wPINMaxExtraDigitL; + pinModifyStructure[offset++] = wPINMaxExtraDigitH; + pinModifyStructure[offset++] = bConfirmPIN; + pinModifyStructure[offset++] = bEntryValidationCondition; + pinModifyStructure[offset++] = bNumberMessage; + pinModifyStructure[offset++] = wLangIdL; + pinModifyStructure[offset++] = wLangIdH; + pinModifyStructure[offset++] = bMsgIndex1; + pinModifyStructure[offset++] = bMsgIndex2; + pinModifyStructure[offset++] = bMsgIndex3; + + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + + pinModifyStructure[offset++] = (byte) apdu.length; + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + pinModifyStructure[offset++] = 0x00; + System.arraycopy(apdu, 0, pinModifyStructure, offset, apdu.length); + +// log.debug("PIN MODIFY " + SMCCHelper.toString(pinModifyStructure)); + return pinModifyStructure; } - /** - * activates pin (newPIN) if not active - * @param pinSpec - * @param oldPIN - * @param newPIN - * @throws at.gv.egiz.smcc.LockedException - * @throws at.gv.egiz.smcc.VerificationFailedException - * @throws at.gv.egiz.smcc.NotActivatedException - * @throws at.gv.egiz.smcc.SignatureCardException - */ @Override - public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) - throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { - Card icc = getCard(); + public void reset() throws SignatureCardException { try { - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); - - if (pinSpec.getContextAID() != null) { - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Select AID " + SMCCHelper.toString(pinSpec.getContextAID()) + - ": SW=" + Integer.toHexString(responseAPDU.getSW()); - log.error(msg); - throw new SignatureCardException(msg); - } - } - - byte[] cmd = new byte[16]; - System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); - System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); - - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0x24, 0x00, pinSpec.getKID(), cmd), false); - - icc.endExclusive(); - - log.debug("change pin returned SW=" + Integer.toHexString(responseAPDU.getSW())); - - // activates pin (newPIN) if not active - if (responseAPDU.getSW() == 0x63c0) { - log.error(pinSpec.getLocalizedName() + " locked"); - throw new LockedException(); - } else if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { - int retries = responseAPDU.getSW2() & 0x0f; - log.error("wrong " + pinSpec.getLocalizedName() + ", " + retries + " retries"); - throw new VerificationFailedException(retries); - } else if (responseAPDU.getSW() == 0x6983) { - log.error(pinSpec.getLocalizedName() + " locked"); - throw new LockedException(); - } else if (responseAPDU.getSW() != 0x9000) { - String msg = "Failed to change " + pinSpec.getLocalizedName() + - ": SW=" + Integer.toHexString(responseAPDU.getSW()); - log.error(msg); - throw new SignatureCardException(msg); + super.reset(); + log.debug("select MF (e-card workaround)"); + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x00, 0x0C)); + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("Failed to select MF after RESET: SW=" + Integer.toHexString(resp.getSW()) + "."); } } catch (CardException ex) { - log.error("Failed to change " + pinSpec.getLocalizedName() + - ": " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); + log.error("Failed to select MF after RESET: " + ex.getMessage(), ex); + throw new SignatureCardException("Failed to select MF after RESET"); } } + public String toString() { + return "e-card"; + } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java index d7763be0..293b9c71 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -77,11 +77,11 @@ public class SWCard implements SignatureCard { private KeyStore certifiedKeyStore; - private String certifiedKeyStorePassword; + private char[] certifiedKeyStorePassword; private KeyStore secureKeyStore; - private String secureKeyStorePassword; + private char[] secureKeyStorePassword; private Certificate certifiedCertificate; @@ -195,7 +195,7 @@ public class SWCard implements SignatureCard { } - private String loadKeyStorePassword(String passwordFileName) throws SignatureCardException { + private char[] loadKeyStorePassword(String passwordFileName) throws SignatureCardException { String fileName = getFileName(passwordFileName); FileInputStream keyStorePasswordFile; @@ -212,7 +212,7 @@ public class SWCard implements SignatureCard { for (int l; (l = reader.read(b)) != -1;) { sb.append(b, 0, l); } - return sb.toString(); + return sb.toString().toCharArray(); } catch (IOException e) { throw new SignatureCardException("Failed to read file '" + passwordFileName + "'."); } @@ -237,7 +237,7 @@ public class SWCard implements SignatureCard { } - private String getPassword(KeyboxName keyboxName) throws SignatureCardException { + private char[] getPassword(KeyboxName keyboxName) throws SignatureCardException { if (keyboxName == KeyboxName.CERITIFIED_KEYPAIR) { if (certifiedKeyStorePassword == null) { @@ -311,7 +311,7 @@ public class SWCard implements SignatureCard { public byte[] createSignature(byte[] hash, KeyboxName keyboxName, PINProvider provider) throws SignatureCardException, InterruptedException { // KeyStore password - String password = getPassword(keyboxName); + char[] password = getPassword(keyboxName); if (password == null) { @@ -325,7 +325,7 @@ public class SWCard implements SignatureCard { } - KeyStore keyStore = getKeyStore(keyboxName, password.toCharArray()); + KeyStore keyStore = getKeyStore(keyboxName, password); PrivateKey privateKey = null; @@ -338,7 +338,7 @@ public class SWCard implements SignatureCard { Key key = null; while (key == null) { try { - key = keyStore.getKey(alias, password.toCharArray()); + key = keyStore.getKey(alias, password); } catch (UnrecoverableKeyException e) { log.info("Failed to get Key from KeyStore. Wrong password?", e); } @@ -399,15 +399,27 @@ public class SWCard implements SignatureCard { } @Override - public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { - return -1; + public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + throws LockedException, NotActivatedException, SignatureCardException { } @Override - public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { + public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) throws SignatureCardException { + throw new UnsupportedOperationException("Not supported yet."); } @Override - public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { + public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) throws CancelledException, SignatureCardException, InterruptedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean ifdSupportsFeature(byte feature) { + return false; } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index 3c2273b9..2097e6d3 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -36,6 +36,14 @@ import javax.smartcardio.CardTerminal; public interface SignatureCard { + /** + * IFD FEATURES + */ + static final Byte FEATURE_VERIFY_PIN_DIRECT = new Byte((byte) 0x06); + static final Byte FEATURE_MODIFY_PIN_DIRECT = new Byte((byte) 0x07); + static final Byte FEATURE_MCT_READER_DIRECT = new Byte((byte) 0x08); + static final Byte FEATURE_IFD_PIN_PROPERTIES = new Byte((byte) 0x0a); + public static class KeyboxName { public static KeyboxName SECURE_SIGNATURE_KEYPAIR = new KeyboxName( @@ -123,29 +131,29 @@ public interface SignatureCard { */ public List getPINSpecs(); - /** - * - * @param pinSpec descriptor which pin to verify - * @param pin may be null to test the PIN status - * @return the number of remaining retries or -1 - * @throws at.gv.egiz.smcc.LockedException - * @throws at.gv.egiz.smcc.NotActivatedException - * @throws at.gv.egiz.smcc.SignatureCardException - */ - public int verifyPIN(PINSpec pinSpec, String pin) - throws LockedException, NotActivatedException, SignatureCardException; + public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException; - public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) - throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException; + public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException; - public void activatePIN(PINSpec pinSpec, String pin) - throws SignatureCardException; + public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) + throws CancelledException, SignatureCardException, InterruptedException; + + public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) + throws CancelledException, SignatureCardException, InterruptedException; + + /** + * TODO + * @return + */ + public boolean ifdSupportsFeature(byte feature); /** * Sets the local for evtl. required callbacks (e.g. PINSpec) * @param locale must not be null; */ public void setLocale(Locale locale); - - + + } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java index ab66e9a1..5146c275 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java @@ -196,7 +196,7 @@ public class SignatureCardFactory { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }, "at.gv.egiz.smcc.ACOSCard")); - + } /** diff --git a/smcc/src/main/java/at/gv/egiz/smcc/TimeoutException.java b/smcc/src/main/java/at/gv/egiz/smcc/TimeoutException.java new file mode 100644 index 00000000..d14a4c15 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/TimeoutException.java @@ -0,0 +1,39 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc; + +public class TimeoutException extends SignatureCardException { + + private static final long serialVersionUID = 1L; + + public TimeoutException() { + super(); + } + + public TimeoutException(String message, Throwable cause) { + super(message, cause); + } + + public TimeoutException(String message) { + super(message); + } + + public TimeoutException(Throwable cause) { + super(cause); + } + +} diff --git a/smcc/src/test/resources/log4j.properties b/smcc/src/test/resources/log4j.properties index 94662fd2..053eac17 100644 --- a/smcc/src/test/resources/log4j.properties +++ b/smcc/src/test/resources/log4j.properties @@ -1,5 +1,5 @@ # loglever DEBUG, appender STDOUT -log4j.rootLogger=DEBUG, STDOUT +log4j.rootLogger=TRACE, STDOUT #log4j.logger.at.gv.egiz.slbinding.RedirectEventFilter=DEBUG, STDOUT # STDOUT appender diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java index 23b71690..14b36e28 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java @@ -136,7 +136,9 @@ public abstract class AbstractBKUWorker extends AbstractSMCCSTAL implements Acti if (oldValue != SMCCHelper.CARD_NOT_SUPPORTED) { actionCommandList.clear(); actionCommandList.add("cancel"); - gui.showCardNotSupportedDialog(this, "cancel"); + gui.showMessageDialog(BKUGUIFacade.TITLE_CARD_NOT_SUPPORTED, + BKUGUIFacade.MESSAGE_CARD_NOT_SUPPORTED, null, + BKUGUIFacade.BUTTON_CANCEL, this, "cancel"); oldValue = SMCCHelper.CARD_NOT_SUPPORTED; } break; @@ -144,7 +146,9 @@ public abstract class AbstractBKUWorker extends AbstractSMCCSTAL implements Acti if (oldValue != SMCCHelper.NO_CARD) { actionCommandList.clear(); actionCommandList.add("cancel"); - gui.showInsertCardDialog(this, "cancel"); + gui.showMessageDialog(BKUGUIFacade.TITLE_INSERTCARD, + BKUGUIFacade.MESSAGE_INSERTCARD, null, + BKUGUIFacade.BUTTON_CANCEL, this, "cancel"); oldValue = SMCCHelper.NO_CARD; } break; diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java new file mode 100644 index 00000000..e32f08d4 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java @@ -0,0 +1,67 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; + +import at.gv.egiz.smcc.PINProvider; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public abstract class AbstractPINProvider implements PINProvider, ActionListener { + + protected static final Log log = LogFactory.getLog(AbstractPINProvider.class); + + protected boolean retry = false; + + protected String action; + + private boolean actionPerformed; + +// protected void waitForAction() throws InterruptedException { +// super.wait(); +// } + + protected synchronized void waitForAction() throws InterruptedException { + try { + while (!actionPerformed) { + this.wait(); + } + } catch (InterruptedException e) { + log.error("interrupt in waitForAction"); + throw e; + } + actionPerformed = false; + } + + private synchronized void actionPerformed() { + actionPerformed = true; + notify();//All(); + } + + @Override + public void actionPerformed(ActionEvent e) { + log.debug("command " + e.getActionCommand()); + action = e.getActionCommand(); + actionPerformed(); + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 1cf81e05..71f35181 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -121,6 +121,12 @@ public abstract class AbstractSMCCSTAL implements STAL { return new ErrorResponse(6000); } + /** + * + * @param requestList + * @return + * @throws RuntimeException with cause InterruptedException if interrupted + */ @Override public List handleRequest(List requestList) { log.debug("Got request list containing " + requestList.size() diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java index 5a54e97f..94444922 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java @@ -33,23 +33,26 @@ import at.gv.egiz.stal.InfoboxReadResponse; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; -public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements - PINProvider { +public class InfoBoxReadRequestHandler extends AbstractRequestHandler { private static Log log = LogFactory.getLog(InfoBoxReadRequestHandler.class); - private int retryCounter = 0; + protected PINProviderFactory pinProviderFactory; @Override public STALResponse handleRequest(STALRequest request) throws InterruptedException { if (request instanceof InfoboxReadRequest) { InfoboxReadRequest infoBox = (InfoboxReadRequest) request; + if (pinProviderFactory == null) { + pinProviderFactory = PINProviderFactory.getInstance(card, gui); + } try { if (infoBox.getInfoboxIdentifier().equals("IdentityLink")) { newSTALMessage("Message.RequestCaption", "Message.IdentityLink"); log.debug("Handling identitylink infobox"); - byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this, - infoBox.getDomainIdentifier()); + byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), + pinProviderFactory.getCardPINProvider(), + infoBox.getDomainIdentifier()); if (resp == null) { log.info("Got null as result->user cancelled"); return new ErrorResponse(6001); @@ -94,8 +97,9 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements newSTALMessage("Message.RequestCaption", "Message.InfoboxReadRequest"); log.warn("Unknown infobox identifier: " + infoBox.getInfoboxIdentifier() + " trying generic request"); - byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this, - infoBox.getDomainIdentifier()); + byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), + pinProviderFactory.getCardPINProvider(), + infoBox.getDomainIdentifier()); if (resp == null) { return new ErrorResponse(6001); } @@ -110,13 +114,15 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements log.info("Citizen card not activated.", e); gui.showErrorDialog(BKUGUIFacade.ERR_CARD_NOTACTIVATED, null, this, null); waitForAction(); - gui.showWaitDialog(null); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); return new ErrorResponse(6001); } catch (LockedException e) { log.info("Citizen card locked.", e); gui.showErrorDialog(BKUGUIFacade.ERR_CARD_LOCKED, null, this, null); waitForAction(); - gui.showWaitDialog(null); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); return new ErrorResponse(6001); } catch (CancelledException cx) { log.debug("User cancelled request", cx); @@ -135,20 +141,4 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements public boolean requireCard() { return true; } - - @Override - public String providePIN(PINSpec spec, int retries) throws InterruptedException { - if (retryCounter++ > 0) { - log.info("PIN wrong retrying ..."); - gui.showCardPINRetryDialog(spec, retries, this, "ok", this, "cancel"); - } else { - gui.showCardPINDialog(spec, this, "ok", this, "cancel"); - } - waitForAction(); - gui.showWaitDialog(null); - if (actionCommand.equals("cancel")) { - return null; - } - return new String(gui.getPin()); - } } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java new file mode 100644 index 00000000..670b71dc --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.stal.signedinfo.SignedInfoType; + +/** + * + * @author Clemens Orthacker + */ +public abstract class PINProviderFactory { + + BKUGUIFacade gui; + + public static PINProviderFactory getInstance(SignatureCard forCard, + BKUGUIFacade gui) { + if (forCard.ifdSupportsFeature(SignatureCard.FEATURE_VERIFY_PIN_DIRECT)) { + return new PinpadPINProviderFactory(gui); + } else { + return new SoftwarePINProviderFactory(gui); + } + } + + public abstract PINProvider getSignaturePINProvider(SecureViewer viewer, + SignedInfoType signedInfo); + + public abstract PINProvider getCardPINProvider(); + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PinpadPINProviderFactory.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PinpadPINProviderFactory.java new file mode 100644 index 00000000..55321b72 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PinpadPINProviderFactory.java @@ -0,0 +1,155 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.util.List; + +/** + * + * @author Clemens Orthacker + */ +public class PinpadPINProviderFactory extends PINProviderFactory { + + protected PinpadPINProviderFactory(BKUGUIFacade gui) { + this.gui = gui; + } + + @Override + public PINProvider getSignaturePINProvider(SecureViewer viewer, + SignedInfoType signedInfo) { + + return new SignaturePinProvider(viewer, signedInfo); + } + + @Override + public PINProvider getCardPINProvider() { + return new CardPinProvider(); + } + + class SignaturePinProvider extends AbstractPINProvider { + +// protected BKUGUIFacade gui; + protected SecureViewer viewer; + protected SignedInfoType signedInfo; + protected List hashDataInputs; + + private SignaturePinProvider(SecureViewer viewer, + SignedInfoType signedInfo) { + this.viewer = viewer; + this.signedInfo = signedInfo; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + showPinpadPINDialog(retries, spec); + retry = true; + return null; + +// do { +// waitForAction(); +// gui.showWaitDialog(null); +// +// if ("hashData".equals(action)) { +// // show pin dialog in background +// gui.showSignaturePINDialog(spec, (retry) ? retries : -1, +// this, "sign", +// this, "cancel", +// this, "hashData"); +// +// viewer.displayDataToBeSigned(signedInfo.getReference()); +// +// } else if ("sign".equals(action)) { +// retry = true; +// return gui.getPin(); +// } else if ("hashDataDone".equals(action)) { +// gui.showSignaturePINDialog(spec, (retry) ? retries : -1, +// this, "sign", +// this, "cancel", +// this, "hashData"); +// } else if ("cancel".equals(action) || +// "error".equals(action)) { +// throw new CancelledException(spec.getLocalizedName() + +// " entry cancelled"); +// } +// } while (true); + } + + private void showPinpadPINDialog(int retries, PINSpec pinSpec) { + String title, message; + Object[] params; + if (retry) { + title = BKUGUIFacade.TITLE_RETRY; + message = BKUGUIFacade.MESSAGE_RETRIES; + params = new Object[]{String.valueOf(retries)}; + } else { + title = BKUGUIFacade.TITLE_SIGN; + message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } + gui.showMessageDialog(title, message, params); + } + } + + class CardPinProvider extends AbstractPINProvider { + + private CardPinProvider() { + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + showPinpadPINDialog(retries, spec); + retry = true; + return null; + + } + + private void showPinpadPINDialog(int retries, PINSpec pinSpec) { + String title, message; + Object[] params; + if (retry) { + title = BKUGUIFacade.TITLE_RETRY; + message = BKUGUIFacade.MESSAGE_RETRIES; + params = new Object[]{String.valueOf(retries)}; + } else { + title = BKUGUIFacade.TITLE_CARDPIN; + message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } + gui.showMessageDialog(title, message, params); + } + } +} + diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java new file mode 100644 index 00000000..c395679a --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java @@ -0,0 +1,44 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; + +import at.gv.egiz.stal.signedinfo.ReferenceType; +import java.security.DigestException; +import java.util.List; + +/** + * + * @author Clemens Orthacker + */ +public interface SecureViewer { + + /** + * Displays the hashdata inputs for all provided dsig:SignedReferences. + * Implementations may verify the digest value if necessary. + * (LocalSignRequestHandler operates on DataObjectHashDataInput, + * other SignRequestHandlers should cache the HashDataInputs obtained by webservice calls, + * or simply forward to a HashDataInputServlet.) + * @param signedReferences The caller may select a subset of the references in SignedInfo to be displayed. + * @throws java.security.DigestException if digest values are verified and do not correspond + * (or any other digest computation error occurs) + * @throws java.lang.Exception + */ + void displayDataToBeSigned(List signedReferences) + throws DigestException, Exception; + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index d041a8cb..ac510f38 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -17,7 +17,6 @@ package at.gv.egiz.bku.smccstal; import at.gv.egiz.bku.gui.BKUGUIFacade; -import java.awt.event.ActionEvent; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.security.MessageDigest; @@ -35,12 +34,11 @@ import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.SignatureCard.KeyboxName; +import at.gv.egiz.smcc.TimeoutException; import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; @@ -48,13 +46,12 @@ import at.gv.egiz.stal.SignResponse; import at.gv.egiz.stal.signedinfo.ObjectFactory; import at.gv.egiz.stal.signedinfo.SignedInfoType; import at.gv.egiz.stal.util.JCEAlgorithmNames; -import java.security.DigestException; -import java.util.List; -public abstract class SignRequestHandler extends AbstractRequestHandler implements HashDataInputDisplay { +public abstract class SignRequestHandler extends AbstractRequestHandler implements SecureViewer { private static Log log = LogFactory.getLog(SignRequestHandler.class); private static JAXBContext jaxbContext; + private PINProviderFactory pinProviderFactory; static { try { @@ -84,7 +81,14 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen MessageDigest md = MessageDigest.getInstance(jceName); md.update(signReq.getSignedInfo()); KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); - byte[] resp = card.createSignature(md.digest(), kb, new STALPinProvider(si.getValue())); + + if (pinProviderFactory == null) { + pinProviderFactory = PINProviderFactory.getInstance(card, gui); + } + PINProvider pinProvider = pinProviderFactory. + getSignaturePINProvider(this, si.getValue()); + + byte[] resp = card.createSignature(md.digest(), kb, pinProvider); if (resp == null) { return new ErrorResponse(6001); } @@ -95,17 +99,28 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen log.info("Citizen card not activated.", e); gui.showErrorDialog(BKUGUIFacade.ERR_CARD_NOTACTIVATED, null, this, null); waitForAction(); - gui.showWaitDialog(null); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); return new ErrorResponse(6001); } catch (LockedException e) { log.info("Citizen card locked.", e); gui.showErrorDialog(BKUGUIFacade.ERR_CARD_LOCKED, null, this, null); waitForAction(); - gui.showWaitDialog(null); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); return new ErrorResponse(6001); } catch (CancelledException cx) { log.debug("User cancelled request"); return new ErrorResponse(6001); + } catch (TimeoutException ex) { + log.error("Timeout during pin entry"); + gui.showMessageDialog(BKUGUIFacade.TITLE_ENTRY_TIMEOUT, + BKUGUIFacade.ERR_PIN_TIMEOUT, null, + BKUGUIFacade.BUTTON_CANCEL, this, null); + waitForAction(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + return new ErrorResponse(6001); } catch (SignatureCardException e) { log.error("Error while creating signature: " + e); return new ErrorResponse(4000); @@ -127,64 +142,64 @@ public abstract class SignRequestHandler extends AbstractRequestHandler implemen return true; } - class STALPinProvider implements PINProvider { - - protected SignedInfoType signedInfo; - protected List hashDataInputs; - private int retryCounter = 0; - - public STALPinProvider(SignedInfoType signedInfo) { - this.signedInfo = signedInfo; - } - - private void showSignaturePINDialog(PINSpec spec, int retries) { - if (retryCounter > 0) { - gui.showSignaturePINRetryDialog(spec, retries, SignRequestHandler.this, "sign", SignRequestHandler.this, - "cancel", SignRequestHandler.this, "hashData"); - } else { - gui.showSignaturePINDialog(spec, SignRequestHandler.this, "sign", SignRequestHandler.this, "cancel", SignRequestHandler.this, - "hashData"); - } - } - - @Override - public String providePIN(PINSpec spec, int retries) throws InterruptedException { - - showSignaturePINDialog(spec, retries); - - do { - waitForAction(); - gui.showWaitDialog(null); - if (actionCommand.equals("cancel")) { - return null; - } else if (actionCommand.equals("hashData")) { - - showSignaturePINDialog(spec, retries); - - try { - displayHashDataInputs(signedInfo.getReference()); - } catch (DigestException ex) { - log.error("Bad digest value: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, new Object[] {ex.getMessage()}, SignRequestHandler.this, "error"); - } catch (Exception ex) { - log.error("Could not display hashdata inputs: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, new Object[] {ex.getMessage()}, SignRequestHandler.this, "error"); - } - - } else if (actionCommand.equals("sign")) { - retryCounter++; - return new String(gui.getPin()); - } else if (actionCommand.equals("hashDataDone")) { - showSignaturePINDialog(spec, retries); - } else if (actionCommand.equals("error")) { - return null; - } - } while (true); - } - +// class SoftwarePinProvider implements PINProvider { +// +// protected SignedInfoType signedInfo; +// protected List hashDataInputs; +// private boolean retry = false; +// +// public SoftwarePinProvider(SignedInfoType signedInfo) { +// this.signedInfo = signedInfo; +// } +// +// private void showSignaturePINDialog(PINSpec spec, int retries) { +// if (retry) { +// gui.showSignaturePINRetryDialog(spec, retries, SignRequestHandler.this, "sign", SignRequestHandler.this, +// "cancel", SignRequestHandler.this, "hashData"); +// } else { +// gui.showSignaturePINDialog(spec, SignRequestHandler.this, "sign", SignRequestHandler.this, "cancel", SignRequestHandler.this, +// "hashData"); +// } +// } +// // @Override -// public void actionPerformed(ActionEvent e) { -// throw new UnsupportedOperationException("Not supported yet."); +// public char[] providePIN(PINSpec spec, int retries) +// throws CancelledException, InterruptedException { +// showSignaturePINDialog(spec, retries); +// +// do { +// waitForAction(); +// gui.showWaitDialog(null); +// if (actionCommand.equals("hashData")) { +// +// showSignaturePINDialog(spec, retries); +// +// try { +// displayHashDataInputs(signedInfo.getReference()); +// +// } catch (DigestException ex) { +// log.error("Bad digest value: " + ex.getMessage()); +// gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, +// new Object[] {ex.getMessage()}, +// SignRequestHandler.this, "error"); +// } catch (Exception ex) { +// log.error("Could not display hashdata inputs: " + +// ex.getMessage()); +// gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, +// new Object[] {ex.getMessage()}, +// SignRequestHandler.this, "error"); +// } +// } else if (actionCommand.equals("sign")) { +// retry = true; +// return gui.getPin(); +// } else if (actionCommand.equals("hashDataDone")) { +// showSignaturePINDialog(spec, retries); +// } else if (actionCommand.equals("cancel") || +// actionCommand.equals("error")) { +// throw new CancelledException(spec.getLocalizedName() + +// " entry cancelled"); +// } +// } while (true); // } - } +// } } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SoftwarePINProviderFactory.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SoftwarePINProviderFactory.java new file mode 100644 index 00000000..54a34280 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SoftwarePINProviderFactory.java @@ -0,0 +1,140 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.*; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.security.DigestException; +import java.util.List; + +/** + * + * @author Clemens Orthacker + */ +public class SoftwarePINProviderFactory extends PINProviderFactory { + + protected SoftwarePINProviderFactory(BKUGUIFacade gui) { + this.gui = gui; + } + + @Override + public PINProvider getSignaturePINProvider(SecureViewer viewer, + SignedInfoType signedInfo) { + return new SignaturePinProvider(viewer, signedInfo); + } + + @Override + public PINProvider getCardPINProvider() { + return new CardPinProvider(); + } + + class SignaturePinProvider extends AbstractPINProvider { + +// protected BKUGUIFacade gui; + protected SecureViewer viewer; + protected SignedInfoType signedInfo; + protected List hashDataInputs; + + private SignaturePinProvider(SecureViewer viewer, + SignedInfoType signedInfo) { + this.viewer = viewer; + this.signedInfo = signedInfo; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, + this, "sign", + this, "cancel", + this, "hashData"); + + do { + waitForAction(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + + if ("hashData".equals(action)) { + // show pin dialog in background + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, + this, "sign", + this, "cancel", + this, "hashData"); + + try { + viewer.displayDataToBeSigned(signedInfo.getReference()); + } catch (DigestException ex) { + log.error("Bad digest value: " + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, + new Object[]{ex.getMessage()}, + this, "error"); + } catch (Exception ex) { + log.error("Could not display hashdata inputs: " + + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, + new Object[]{ex.getMessage()}, + this, "error"); + } + } else if ("sign".equals(action)) { + retry = true; + return gui.getPin(); + } else if ("hashDataDone".equals(action)) { + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, + this, "sign", + this, "cancel", + this, "hashData"); + } else if ("cancel".equals(action) || + "error".equals(action)) { + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } + } while (true); + } + } + + class CardPinProvider extends AbstractPINProvider { + +// protected BKUGUIFacade gui; + + private CardPinProvider() { + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + gui.showCardPINDialog(spec, (retry) ? retries : -1, + this, "ok", + this, "cancel"); + + waitForAction(); + + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + + if ("cancel".equals(action)) { + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } + retry = true; + return gui.getPin(); + } + } +} diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java index b2a91784..51dfe0da 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -93,16 +93,24 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements } @Override - public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { - return -1; + public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) { } @Override - public void changePIN(PINSpec pinSpec, String oldPIN, String newPIN) throws LockedException, VerificationFailedException, NotActivatedException, SignatureCardException { + public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) { } @Override - public void activatePIN(PINSpec pinSpec, String pin) throws SignatureCardException { + public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) { + } + + @Override + public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) { + } + + @Override + public boolean ifdSupportsFeature(byte feature) { + return false; } }; -- cgit v1.2.3 From 616e06910051528674165319a1d6d161dff5859c Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 27 Mar 2009 17:33:11 +0000 Subject: 1.1-RC6 (pinpad, pinmgmt, secureviewer) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@323 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/online/applet/AppletBKUWorker.java | 5 +- .../egiz/bku/online/applet/AppletSecureViewer.java | 79 +-- .../at/gv/egiz/bku/online/applet/BKUApplet.java | 10 +- .../java/at/gv/egiz/bku/gui/PINManagementGUI.java | 26 +- .../at/gv/egiz/bku/gui/PINManagementGUIFacade.java | 9 +- .../java/at/gv/egiz/bku/gui/PINStatusRenderer.java | 2 - .../smccstal/ext/ManagementPINProviderFactory.java | 13 +- .../bku/smccstal/ext/PinpadPINProviderFactory.java | 45 +- .../gv/egiz/bku/gui/ActivationMessages.properties | 6 +- .../egiz/bku/gui/ActivationMessages_en.properties | 6 +- .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 40 +- .../main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java | 603 +++++++++++++-------- .../java/at/gv/egiz/bku/gui/HashDataViewer.java | 293 ---------- .../at/gv/egiz/bku/gui/SecureViewerDialog.java | 371 +++++++++++++ .../at/gv/egiz/bku/gui/Messages.properties | 3 +- .../at/gv/egiz/bku/gui/Messages_en.properties | 1 + .../src/main/resources/images/ChipperlingLogo.png | Bin 0 -> 4035 bytes .../test/java/at/gv/egiz/bku/gui/BKUGUITest.java | 5 +- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 4 +- .../at/gv/egiz/bku/local/stal/BKUGuiProxy.java | 8 + .../at/gv/egiz/bku/local/stal/LocalBKUWorker.java | 3 +- .../gv/egiz/bku/local/stal/LocalSecureViewer.java | 109 ++++ .../bku/local/stal/LocalSignRequestHandler.java | 83 +-- .../gv/egiz/bku/online/conf/defaultConf.properties | 3 + BKUOnline/src/main/resources/log4j.properties | 2 +- BKUOnline/src/main/webapp/SLRequestForm.html | 27 + .../at/gv/egiz/bku/binding/ExpiryRemoverTest.java | 101 ++-- smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 130 ++--- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 220 ++------ .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 234 +++++--- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 49 +- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 15 +- smcc/src/main/java/at/gv/egiz/smcc/ccid/CCID.java | 77 +++ .../java/at/gv/egiz/smcc/ccid/DefaultReader.java | 264 +++++++++ .../at/gv/egiz/smcc/ccid/GemplusGemPCPinpad.java | 65 +++ .../java/at/gv/egiz/smcc/ccid/ReaderFactory.java | 35 ++ .../test/java/at/gv/egiz/smcc/ACOSCardTest.java | 135 +++++ .../test/java/at/gv/egiz/smcc/STARCOSCardTest.java | 267 +++++++++ .../gv/egiz/bku/smccstal/AbstractPINProvider.java | 2 +- .../gv/egiz/bku/smccstal/PINProviderFactory.java | 3 +- .../bku/smccstal/PinpadPINProviderFactory.java | 131 +++-- .../java/at/gv/egiz/bku/smccstal/SecureViewer.java | 11 +- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 14 +- .../bku/smccstal/SoftwarePINProviderFactory.java | 25 +- .../java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java | 7 +- 45 files changed, 2364 insertions(+), 1177 deletions(-) delete mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java create mode 100644 BKUCommonGUI/src/main/resources/images/ChipperlingLogo.png create mode 100644 BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSecureViewer.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ccid/CCID.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ccid/GemplusGemPCPinpad.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ccid/ReaderFactory.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/ACOSCardTest.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/STARCOSCardTest.java (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java index 9b9735f6..e8d8976d 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java @@ -18,6 +18,7 @@ package at.gv.egiz.bku.online.applet; import at.gv.egiz.bku.smccstal.AbstractBKUWorker; import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.smccstal.SignRequestHandler; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; @@ -67,8 +68,10 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { STALPortType stalPort = applet.getSTALPort(); STALTranslator stalTranslator = applet.getSTALTranslator(); + AppletSecureViewer secureViewer = + new AppletSecureViewer(gui, stalPort, sessionId); addRequestHandler(SignRequest.class, - new AppletSecureViewer(stalPort, sessionId)); + new SignRequestHandler(secureViewer)); GetNextRequestResponseType nextRequestResp = stalPort.connect(sessionId); diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java index e2551e2d..929cecb1 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java @@ -16,17 +16,8 @@ */ package at.gv.egiz.bku.online.applet; +import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.smccstal.SecureViewer; -import java.security.DigestException; -import java.security.MessageDigest; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.smccstal.SignRequestHandler; import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.impl.ByteArrayHashDataInput; import at.gv.egiz.stal.service.GetHashDataInputFault; @@ -34,49 +25,73 @@ import at.gv.egiz.stal.service.STALPortType; import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; import at.gv.egiz.stal.service.types.GetHashDataInputType; import at.gv.egiz.stal.signedinfo.ReferenceType; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.awt.event.ActionListener; +import java.security.DigestException; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** - * A SignRequesthandler that obtains hashdata inputs from a STAL webservice and - * displays these either within the applet or in a separate frame. - * The internal viewer displays plaintext data only, other mimetypes can be saved to disk. - * The standalone (frame) viewer displays all mimetypes. - * - * (This class depends on STALService and therefore is not part of BKUCommonGUI.) - * + * * @author Clemens Orthacker */ -public class AppletSecureViewer extends SignRequestHandler { +public class AppletSecureViewer implements SecureViewer { private static final Log log = LogFactory.getLog(AppletSecureViewer.class); + + protected BKUGUIFacade gui; protected STALPortType stalPort; protected String sessId; + protected List verifiedDataToBeSigned; - public AppletSecureViewer(STALPortType stalPort, String sessId) { - if (stalPort == null || sessId == null) { + public AppletSecureViewer(BKUGUIFacade gui, STALPortType stalPort, + String sessId) { + if (gui == null) { + throw new NullPointerException("GUI must not be null"); + } + if (stalPort == null) { throw new NullPointerException("STAL port must not be null"); } - this.sessId = sessId; + if (sessId == null) { + throw new NullPointerException("session id must not be null"); + } + this.gui = gui; this.stalPort = stalPort; + this.sessId = sessId; } /** - * TODO don't throw exceptions + * retrieves the data to be signed for * @param signedReferences + * @param okListener + * @param okCommand + * @param cancelListener + * @param cancelCommand * @throws java.security.DigestException * @throws java.lang.Exception */ @Override - public void displayDataToBeSigned(List signedReferences) + public void displayDataToBeSigned(SignedInfoType signedInfo, + ActionListener okListener, String okCommand) throws DigestException, Exception { - - List hdi = getHashDataInput(signedReferences); - List verifiedHashDataInputs = verifyHashDataInput(signedReferences, hdi); - - if (verifiedHashDataInputs.size() > 0) { - gui.showSecureViewer(verifiedHashDataInputs, this, "hashDataDone"); + + if (verifiedDataToBeSigned == null) { + log.info("retrieve data to be signed for dsig:SignedInfo " + + signedInfo.getId()); + List hdi = + getHashDataInput(signedInfo.getReference()); + verifiedDataToBeSigned = verifyHashDataInput(signedInfo.getReference(), + hdi); + } + if (verifiedDataToBeSigned.size() > 0) { + gui.showSecureViewer(verifiedDataToBeSigned, okListener, okCommand); } else { - throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); + throw new Exception("No data to be signed (apart from any QualifyingProperties or a Manifest)"); } } @@ -110,7 +125,7 @@ public class AppletSecureViewer extends SignRequestHandler { } } } - + if (request.getReference().size() < 1) { log.error("No signature data (apart from any QualifyingProperties or a Manifest) for session " + sessId); throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); @@ -187,7 +202,7 @@ public class AppletSecureViewer extends SignRequestHandler { verifiedHashDataInputs.add(new ByteArrayHashDataInput(hdi, signedRefId, mimeType, encoding)); } } - + return verifiedHashDataInputs; } diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java index a4337bbd..0ddb6dc6 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java @@ -34,6 +34,7 @@ import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.BKUGUIImpl; import at.gv.egiz.stal.service.STALPortType; import at.gv.egiz.stal.service.STALService; +import java.applet.AppletContext; import java.awt.Container; import javax.xml.namespace.QName; @@ -207,14 +208,19 @@ public class BKUApplet extends JApplet { */ protected void sendRedirect(String sessionId) { try { + AppletContext ctx = getAppletContext(); + if (ctx == null) { + log.error("no applet context (applet might already have been destroyed)"); + return; + } URL redirectURL = getURLParameter(REDIRECT_URL, sessionId); String redirectTarget = getParameter(REDIRECT_TARGET); if (redirectTarget == null) { log.info("Done. Redirecting to " + redirectURL + " ..."); - getAppletContext().showDocument(redirectURL); + ctx.showDocument(redirectURL); } else { log.info("Done. Redirecting to " + redirectURL + " (target=" + redirectTarget + ") ..."); - getAppletContext().showDocument(redirectURL, redirectTarget); + ctx.showDocument(redirectURL, redirectTarget); } } catch (MalformedURLException ex) { log.warn("Failed to redirect: " + ex.getMessage(), ex); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java index 159dd29d..d1ca6c00 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -118,18 +118,18 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac pinStatusTable.setDefaultRenderer(PINSpec.class, new PINSpecRenderer()); pinStatusTable.setDefaultRenderer(STATUS.class, new PINStatusRenderer(cardmgmtMessages)); pinStatusTable.setTableHeader(null); - - pinStatusTable.addMouseMotionListener(new MouseMotionAdapter() { - - @Override - public void mouseMoved(MouseEvent e) { - if (pinStatusTable.columnAtPoint(e.getPoint()) == 0) { - pinStatusTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } else { - pinStatusTable.setCursor(Cursor.getDefaultCursor()); - } - } - }); + pinStatusTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); +// pinStatusTable.addMouseMotionListener(new MouseMotionAdapter() { +// +// @Override +// public void mouseMoved(MouseEvent e) { +// if (pinStatusTable.columnAtPoint(e.getPoint()) == 0) { +// pinStatusTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); +// } else { +// pinStatusTable.setCursor(Cursor.getDefaultCursor()); +// } +// } +// }); final JButton activateButton = new JButton(); activateButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -392,7 +392,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac if (pinpad) { JLabel pinpadLabel = new JLabel(); pinpadLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); - String pinpadPattern = getMessage(MESSAGE_PINPAD); + String pinpadPattern = getMessage(MESSAGE_VERIFYPIN_PINPAD); pinpadLabel.setText(MessageFormat.format(pinpadPattern, new Object[] { pinSpec.getLocalizedName(), pinSize })); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java index 45313f42..f0cc0a27 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -40,13 +40,16 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String MESSAGE_ACTIVATE_SUCCESS = "activate.success"; public static final String MESSAGE_CHANGE_SUCCESS = "change.success"; public static final String MESSAGE_PINMGMT = "pin.mgmt"; - public static final String MESSAGE_PINPAD = "pinpad"; - public static final String MESSAGE_CHANGEPIN_PINPAD = "pinpad.change"; +// public static final String MESSAGE_PINPAD = "pinpad"; public static final String MESSAGE_ACTIVATE_PIN = "activate.pin"; public static final String MESSAGE_CHANGE_PIN = "change.pin"; public static final String MESSAGE_VERIFY_PIN = "verify.pin"; public static final String MESSAGE_UNBLOCK_PIN = "unblock.pin"; - + public static final String MESSAGE_ACTIVATEPIN_PINPAD = "activate.pinpad"; + public static final String MESSAGE_CHANGEPIN_PINPAD = "change.pinpad"; + public static final String MESSAGE_VERIFYPIN_PINPAD = "verify.pinpad"; + public static final String MESSAGE_UNBLOCKPIN_PINPAD = "unblock.pinpad"; + public static final String LABEL_OLD_PIN = "label.old.pin"; public static final String LABEL_NEW_PIN = "label.new.pin"; public static final String LABEL_REPEAT_PIN = "label.repeat.pin"; diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java index 4cb84b77..83ff74f2 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java @@ -22,8 +22,6 @@ import java.awt.Color; import java.awt.Font; import java.util.ResourceBundle; import javax.swing.table.DefaultTableCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java index b0dd8766..d635b8df 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java @@ -19,6 +19,7 @@ package at.gv.egiz.bku.smccstal.ext; import at.gv.egiz.smcc.ChangePINProvider; import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.smcc.ccid.CCID; import at.gv.egiz.smcc.PINProvider; import at.gv.egiz.smcc.SignatureCard; @@ -33,13 +34,13 @@ public abstract class ManagementPINProviderFactory { public static ManagementPINProviderFactory getInstance(SignatureCard forCard, PINManagementGUIFacade gui) { -// if (forCard.ifdSupportsFeature(SignatureCard.FEATURE_VERIFY_PIN_DIRECT)) { -//// forCard.ifdSupportsFeature(SignatureCard.FEATURE_MODIFY_PIN_DIRECT) -// return new PinpadPINProviderFactory(gui); -// -// } else { + if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { +// forCard.ifdSupportsFeature(SignatureCard.FEATURE_MODIFY_PIN_DIRECT) + return new PinpadPINProviderFactory(gui); + + } else { return new SoftwarePINProviderFactory(gui); -// } + } } public abstract PINProvider getVerifyPINProvider(); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java index 4176e0a9..a9ad5ef8 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java @@ -73,23 +73,6 @@ public class PinpadPINProviderFactory extends ManagementPINProviderFactory { showPinpadPINDialog(retries, spec); retry = true; return null; - -// gui.showPINDialog(type, spec, (retry) ? retries : -1, -// this, "exec", -// this, "back"); -// -// waitForAction(); -// -// if ("exec".equals(action)) { -// gui.showWaitDialog(null); -// retry = true; -// return gui.getPin(); -// } else if ("back".equals(action)) { -// throw new CancelledException(); -// } else { -// log.error("unsupported command " + action); -// throw new CancelledException(); -// } } /** @@ -111,14 +94,38 @@ public class PinpadPINProviderFactory extends ManagementPINProviderFactory { title = BKUGUIFacade.TITLE_RETRY; message = BKUGUIFacade.MESSAGE_RETRIES; params = new Object[]{String.valueOf(retries)}; - } else { - title = BKUGUIFacade.TITLE_SIGN; + } else if (type == DIALOG.VERIFY) { + title = PINManagementGUIFacade.TITLE_VERIFY_PIN; message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; String pinSize = String.valueOf(pinSpec.getMinLength()); if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { pinSize += "-" + pinSpec.getMaxLength(); } params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else if (type == DIALOG.ACTIVATE) { + title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; + message = PINManagementGUIFacade.MESSAGE_ACTIVATEPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else if (type == DIALOG.CHANGE) { + title = PINManagementGUIFacade.TITLE_CHANGE_PIN; + message = PINManagementGUIFacade.MESSAGE_CHANGEPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else { //if (type == DIALOG.UNBLOCK) { + title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; + message = PINManagementGUIFacade.MESSAGE_UNBLOCKPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; } gui.showMessageDialog(title, message, params); } diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties index 4ceacb21..c6d219d4 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -24,12 +24,14 @@ title.change.success=Erfolg # removed message.* prefix to reuse keys as help keys pin.mgmt=Die Karte verf\u00FCgt \u00FCber {0} PINs -pinpad={0} ({1} stellig) am Kartenleser eingeben und best\u00E4tigen. -pinpad.change={0} ({1} stellig) am Kartenleser eingeben und best\u00E4tigen. activate.pin={0} eingeben und best\u00E4tigen change.pin={0} eingeben und best\u00E4tigen unblock.pin=PUK zu {0} eingeben verify.pin={0} eingeben (TODO: Warning not activated) +verify.pinpad={0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen). +activate.pinpad={0} ({1} stellig) am Kartenleser eingeben und wiederholen (jeweils best\u00E4tigen). +change.pinpad=Alte {0} ({1} stellig) am Kartenleser eingeben, danach neue {0} eingeben und wiederholen (jeweils best\u00E4tigen). +unblock.pinpad={0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen). activate.success={0} wurde erfolgreich aktiviert. change.success={0} wurde erfolgreich ge\u00E4ndert. diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties index 9178d65c..b4bededf 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -23,11 +23,13 @@ title.change.success=Success # removed message.* prefix to reuse keys as help keys pin.mgmt=The smartcard has {0} PINs -pinpad=Enter {0} ({1} digits) on pinpad and confirm. -pinpad.change=Enter {0} ({1} digits) on pinpad and confirm. activate.pin=Enter and confirm {0} change.pin=Enter and confirm {0} unblock.pin=Enter PUK for {0} +verify.pinpad=Enter {0} ({1} digits) on cardreader (and confirm). +activate.pinpad=Enter {0} ({1} digits) on cardreader and repeat (confirm in each case). +change.pinpad=Enter old {0} ({1} digits) on cardreader, then enter new {0} and repeat (confirm in each case). +unblock.pinpad=Enter {0} ({1} digits) on cardreader (and confirm). activate.success={0} successfully activated change.success={0} successfully changed diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index 1043b6a1..4b079428 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -43,6 +43,7 @@ public interface BKUGUIFacade { public static final String MESSAGES_BUNDLE = "at/gv/egiz/bku/gui/Messages"; public static final String DEFAULT_BACKGROUND = "/images/BackgroundChipperling.png"; + public static final String DEFAULT_ICON = "/images/ChipperlingLogo.png"; public static final String HELP_IMG = "/images/help.png"; public static final String HASHDATA_FONT = "Monospaced"; public static final Color ERROR_COLOR = Color.RED; @@ -58,6 +59,7 @@ public interface BKUGUIFacade { public static final String TITLE_WAIT = "title.wait"; public static final String TITLE_HASHDATA = "title.hashdata"; public static final String WINDOWTITLE_SAVE = "windowtitle.save"; + public static final String WINDOWTITLE_ERROR = "windowtitle.error"; public static final String WINDOWTITLE_SAVEDIR = "windowtitle.savedir"; public static final String WINDOWTITLE_OVERWRITE = "windowtitle.overwrite"; public static final String WINDOWTITLE_VIEWER = "windowtitle.viewer"; @@ -102,42 +104,36 @@ public interface BKUGUIFacade { public enum Style { tiny, simple, advanced }; -// public void init(Container contentPane, Locale locale, Style guiStyle, URL background, ActionListener helpListener); - /** * BKUWorker needs to init signature card with locale * @return */ public Locale getLocale(); -// public void showWelcomeDialog(); - - /** - * - * @param waitMessage if null, a simple 'please wait' text is displayed - */ -// public void showWaitDialog(String waitMessage); - -// public void showInsertCardDialog(ActionListener cancelListener, String actionCommand); - -// public void showCardNotSupportedDialog(ActionListener cancelListener, String actionCommand); - public void showCardPINDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); -// public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); - - public void showSignaturePINDialog(PINSpec pinSpec, int numRetries, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); - -// public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); + public void showSignaturePINDialog(PINSpec pinSpec, int numRetries, + ActionListener signListener, String signCommand, + ActionListener cancelListener, String cancelCommand, + ActionListener viewerListener, String viewerCommand); -// public void showPinpadSignaturePINDialog(PINSpec pinSpec, int retries); + public void showPinpadSignaturePINDialog(PINSpec pinSpec, int numRetries, + ActionListener viewerListener, String viewerCommand); public char[] getPin(); - public void showSecureViewer(List signedReferences, - ActionListener okListener, String okCommand); + /** + * + * @param dataToBeSigned + * @param backListener if list of references hides pin dialog, backListener + * receives an action when user hits 'back' button (i.e. whenever the pin-dialog + * needs to be re-paint) + * @param backCommand + */ + public void showSecureViewer(List dataToBeSigned, + ActionListener backListener, String backCommand); public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, String okCommand); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java index 928be249..a7eebbfd 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -71,6 +71,7 @@ public class BKUGUIImpl implements BKUGUIFacade { } protected HelpMouseListener helpListener; + protected SecureViewerDialog secureViewer; protected Container contentPane; protected ResourceBundle messages; @@ -145,13 +146,16 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("initializing gui"); + log.debug("initializing gui [" + Thread.currentThread().getName() + "]"); if (renderIconPanel) { initIconPanel(background); initContentPanel(null); } else { - initContentPanel(background); + initContentPanel((background == null) ? + getClass().getResource(DEFAULT_BACKGROUND) : + background + ); } GroupLayout layout = new GroupLayout(contentPane); @@ -159,15 +163,27 @@ public class BKUGUIImpl implements BKUGUIFacade { if (renderIconPanel) { layout.setHorizontalGroup(layout.createSequentialGroup() - .addComponent(iconPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); - layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(iconPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); + .addContainerGap() + .addComponent(iconPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()); + layout.setVerticalGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(iconPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()); } else { - layout.setHorizontalGroup(layout.createSequentialGroup().addComponent(contentPanel)); - layout.setVerticalGroup(layout.createSequentialGroup().addComponent(contentPanel)); + layout.setHorizontalGroup(layout.createSequentialGroup() + // left border + .addContainerGap() + .addComponent(contentPanel) + .addContainerGap()); + layout.setVerticalGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(contentPanel) + .addContainerGap()); } } }); @@ -178,11 +194,12 @@ public class BKUGUIImpl implements BKUGUIFacade { protected void initIconPanel(URL background) { if (background == null) { - background = getClass().getResource(DEFAULT_BACKGROUND); + background = getClass().getResource(DEFAULT_ICON); } if ("file".equals(background.getProtocol())) { - log.warn("file:// background images not permitted: " + background); - background = getClass().getResource(DEFAULT_BACKGROUND); + log.warn("file:// background images not permitted: " + background + + ", loading default background"); + background = getClass().getResource(DEFAULT_ICON); } log.debug("loading icon panel background " + background); @@ -194,26 +211,24 @@ public class BKUGUIImpl implements BKUGUIFacade { iconPanel.setLayout(iconPanelLayout); iconPanelLayout.setHorizontalGroup( iconPanelLayout.createSequentialGroup() - .addContainerGap() .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); - // no gap here (contentPanel has containerGap) iconPanelLayout.setVerticalGroup( iconPanelLayout.createSequentialGroup() - .addContainerGap() - .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); + .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); } protected void initContentPanel(URL background) { +// if (background == null) { +// background = getClass().getResource(DEFAULT_BACKGROUND); +// } if (background == null) { - background = getClass().getResource(DEFAULT_BACKGROUND); - } - if (background == null) { + log.debug("no background image set"); contentPanel = new JPanel(); } else { if ("file".equals(background.getProtocol())) { - log.warn("file:// background images not permitted: " + background); + log.warn("file:// background images not permitted: " + background + + ", loading default background"); background = getClass().getResource(DEFAULT_BACKGROUND); } log.debug("loading background " + background); @@ -257,34 +272,29 @@ public class BKUGUIImpl implements BKUGUIFacade { GroupLayout contentPanelLayout = new GroupLayout(contentPanel); contentPanel.setLayout(contentPanelLayout); - GroupLayout.ParallelGroup horizontalContentInner = contentPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + // align header, main and button to the right + GroupLayout.ParallelGroup horizontalContent = + contentPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING); //LEADING); + GroupLayout.SequentialGroup verticalContent = + contentPanelLayout.createSequentialGroup(); + if (renderHeaderPanel) { - horizontalContentInner + horizontalContent .addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); + verticalContent + .addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); + } - horizontalContentInner + horizontalContent .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); - GroupLayout.SequentialGroup horizontalContentOuter = contentPanelLayout.createSequentialGroup(); - if (!renderIconPanel) { - horizontalContentOuter - .addContainerGap(); - } - horizontalContentOuter - .addGroup(horizontalContentInner) - .addContainerGap(); - contentPanelLayout.setHorizontalGroup(horizontalContentOuter); - - GroupLayout.SequentialGroup verticalContent = contentPanelLayout.createSequentialGroup(); - verticalContent.addContainerGap(); - if (renderHeaderPanel) { - verticalContent.addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); - } - verticalContent.addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap(); + .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); //Short.MAX_VALUE); + verticalContent + .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); + + contentPanelLayout.setHorizontalGroup(horizontalContent); //Outer); contentPanelLayout.setVerticalGroup(verticalContent); } @@ -521,7 +531,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show card-pin dialog"); + log.debug("show card-pin dialog [" + Thread.currentThread().getName() + "]"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -653,7 +663,6 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonPanel.setLayout(buttonPanelLayout); GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); GroupLayout.Group buttonVertical; @@ -700,6 +709,128 @@ public class BKUGUIImpl implements BKUGUIFacade { // showSignaturePINDialog(pinSpec, -1, signListener, signCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); // } + @Override + public void showPinpadSignaturePINDialog(final PINSpec pinSpec, final int numRetries, +// final ActionListener cancelListener, final String cancelCommand, + final ActionListener hashdataListener, final String hashdataCommand) { + + log.debug("scheduling pinpad signature-pin dialog"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("show pinpad signature-pin dialog [" + Thread.currentThread().getName() + "]"); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + if (renderHeaderPanel) { + if (numRetries < 0) { + titleLabel.setText(getMessage(TITLE_SIGN)); + } else { + titleLabel.setText(getMessage(TITLE_RETRY)); + } + } + + JLabel infoLabel = new JLabel(); + if (numRetries < 0) { + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); + } + infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + infoLabel.setForeground(HYPERLINK_COLOR); + infoLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent me) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); + hashdataListener.actionPerformed(e); + } + }); + helpListener.setHelpTopic(HELP_SIGNPIN); + } else { + String retryPattern; + if (numRetries < 2) { + retryPattern = getMessage(MESSAGE_LAST_RETRY); + } else { + retryPattern = getMessage(MESSAGE_RETRIES); + } + infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); + infoLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); + } + + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + + String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD); + String msg = MessageFormat.format(msgPattern, new Object[] { + pinSpec.getLocalizedName(), pinSize }); + + JLabel msgLabel = new JLabel(); + msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD)); + msgLabel.setText(msg); + + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(infoLabel); + GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(infoLabel); + + if (!renderHeaderPanel) { + infoHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + infoVertical + .addComponent(helpLabel); + } + + mainPanelLayout.setHorizontalGroup( + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(infoHorizontal) + .addComponent(msgLabel)); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(infoVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(msgLabel)); + + //no cancel button (cancel via pinpad) +// if (renderCancelButton) { +// JButton cancelButton = new JButton(); +// cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +// cancelButton.setText(getMessage(BUTTON_CANCEL)); +// cancelButton.setActionCommand(cancelCommand); +// cancelButton.addActionListener(cancelListener); +// +// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); +// buttonPanel.setLayout(buttonPanelLayout); +// +// GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() +// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); +// GroupLayout.SequentialGroup buttonVertical = buttonPanelLayout.createSequentialGroup() +// .addComponent(cancelButton); +// +// buttonPanelLayout.setHorizontalGroup(buttonHorizontal); +// buttonPanelLayout.setVerticalGroup(buttonVertical); +// } + + contentPanel.validate(); + } + }); + } + @Override public void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener signListener, final String signCommand, @@ -717,7 +848,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show signature-pin dialog"); + log.debug("show signature-pin dialog [" + Thread.currentThread().getName() + "]"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -730,6 +861,38 @@ public class BKUGUIImpl implements BKUGUIFacade { } } + JLabel infoLabel = new JLabel(); + if (numRetries < 0) { + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); + } + infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + infoLabel.setForeground(HYPERLINK_COLOR); + infoLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent me) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); + hashdataListener.actionPerformed(e); + } + }); + helpListener.setHelpTopic(HELP_SIGNPIN); + } else { + String retryPattern; + if (numRetries < 2) { + retryPattern = getMessage(MESSAGE_LAST_RETRY); + } else { + retryPattern = getMessage(MESSAGE_RETRIES); + } + infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); + infoLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); + } + JButton signButton = new JButton(); signButton.setFont(signButton.getFont().deriveFont(signButton.getFont().getStyle() & ~java.awt.Font.BOLD)); signButton.setText(getMessage(BUTTON_SIGN)); @@ -765,46 +928,14 @@ public class BKUGUIImpl implements BKUGUIFacade { } pinsizeLabel.setText(MessageFormat.format(pinsizePattern, new Object[]{pinSize})); - JLabel infoLabel = new JLabel(); - if (numRetries < 0) { - infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - if (shortText) { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); - } else { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); - } - infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - infoLabel.setForeground(HYPERLINK_COLOR); - infoLabel.addMouseListener(new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent me) { - ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); - hashdataListener.actionPerformed(e); - } - }); - helpListener.setHelpTopic(HELP_SIGNPIN); - } else { - String retryPattern; - if (numRetries < 2) { - retryPattern = getMessage(MESSAGE_LAST_RETRY); - } else { - retryPattern = getMessage(MESSAGE_RETRIES); - } - infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); - infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); - infoLabel.setForeground(ERROR_COLOR); - helpListener.setHelpTopic(HELP_RETRY); - } - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); - + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() .addComponent(infoLabel); GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(infoLabel); - + if (!renderHeaderPanel) { infoHorizontal .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) @@ -814,8 +945,8 @@ public class BKUGUIImpl implements BKUGUIFacade { } // align pinfield and pinsize to the right - GroupLayout.ParallelGroup pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING); - GroupLayout.Group pinVertical; + GroupLayout.Group pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING); + GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup(); if (pinLabelPos == PinLabelPosition.ABOVE) { pinHorizontal @@ -823,20 +954,25 @@ public class BKUGUIImpl implements BKUGUIFacade { .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); - pinVertical = mainPanelLayout.createSequentialGroup() + pinVertical .addComponent(signPinLabel) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); - } else { + .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel); + } else { // PinLabelPosition.LEFT pinHorizontal .addGroup(mainPanelLayout.createSequentialGroup() .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); - pinVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(signPinLabel) - .addComponent(pinField); + pinVertical + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(signPinLabel) + .addComponent(pinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel); } mainPanelLayout.setHorizontalGroup( @@ -848,18 +984,14 @@ public class BKUGUIImpl implements BKUGUIFacade { mainPanelLayout.createSequentialGroup() .addGroup(infoVertical) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pinVertical) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinsizeLabel)); + .addGroup(pinVertical)); GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); buttonPanel.setLayout(buttonPanelLayout); - GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup(); GroupLayout.Group buttonVertical; - + if (renderCancelButton) { JButton cancelButton = new JButton(); cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -868,17 +1000,19 @@ public class BKUGUIImpl implements BKUGUIFacade { cancelButton.addActionListener(cancelListener); buttonHorizontal + .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); - buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(signButton) - .addComponent(cancelButton); + .addComponent(cancelButton); } else { + buttonHorizontal + .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); buttonVertical = buttonPanelLayout.createSequentialGroup() .addComponent(signButton); } - + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); buttonPanelLayout.setVerticalGroup(buttonVertical); @@ -951,7 +1085,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show message dialog"); + log.debug("show message dialog [" + Thread.currentThread().getName() + "]"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -1011,7 +1145,6 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonPanelLayout.setHorizontalGroup( buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); buttonPanelLayout.setVerticalGroup( buttonPanelLayout.createSequentialGroup() @@ -1084,68 +1217,69 @@ public class BKUGUIImpl implements BKUGUIFacade { } return null; } + + + //////////////////////////////////////////////////////////////////////////// + // SECURE VIEWER + //////////////////////////////////////////////////////////////////////////// + /** - * TODO handle multiple references in HashDataViewer * @param signedReferences - * @param okListener + * @param backListener gets notified if pin-dialog has to be redrawn + * (signedRefencesList returns via BACK button) * @param okCommand */ @Override - public void showSecureViewer(final List signedReferences, - final ActionListener okListener, - final String okCommand) { - - if (signedReferences == null) { - showErrorDialog(getMessage(ERR_NO_HASHDATA), new Object[] {"No SignedReferences provided"}, okListener, okCommand); - return; - } + public void showSecureViewer(final List dataToBeSigned, + final ActionListener backListener, final String backCommand) { - if (signedReferences.size() == 1) { + if (dataToBeSigned == null) { + showErrorDialog(getMessage(ERR_NO_HASHDATA), + new Object[] {"no signature data provided"}, + backListener, backCommand); + } else if (dataToBeSigned.size() == 1) { try { - log.debug("scheduling hashdata viewer"); + log.debug("scheduling secure viewer"); - SwingUtilities.invokeAndWait(new Runnable() { + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - ActionListener saveHashDataListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - HashDataInput hdi = signedReferences.get(0); - showSaveHashDataInputDialog(Collections.singletonList(hdi), okListener, okCommand); - } - }; - showHashDataViewer(signedReferences.get(0), saveHashDataListener, "save"); + showSecureViewer(dataToBeSigned.get(0)); } }); - } catch (InterruptedException ex) { - log.error("Failed to display HashDataViewer: " + ex.getMessage()); - } catch (InvocationTargetException ex) { - log.error("Failed to display HashDataViewer: " + ex.getMessage()); + } catch (Exception ex) { //InterruptedException InvocationTargetException + log.error("Failed to display secure viewer: " + ex.getMessage()); + log.trace(ex); + showErrorDialog(ERR_UNKNOWN, null, backListener, backCommand); } } else { - showSignedReferencesListDialog(signedReferences, okListener, okCommand); + showSignedReferencesListDialog(dataToBeSigned, backListener, backCommand); } } /** * has to be called from event dispatcher thread + * This method blocks until the dialog's close button is pressed. * @param hashDataText * @param saveListener * @param saveCommand */ - private void showHashDataViewer(final HashDataInput hashDataInput, final ActionListener saveListener, final String saveCommand) { + private void showSecureViewer(HashDataInput dataToBeSigned) { - log.debug("show hashdata viewer"); - - ActionListener l = helpListener.getActionListener(); - HashDataViewer.showHashDataInput(contentPane, hashDataInput, messages, saveListener, saveCommand, l); + log.debug("show secure viewer [" + Thread.currentThread().getName() + "]"); + if (secureViewer == null) { + secureViewer = new SecureViewerDialog(null, messages, + helpListener.getActionListener()); + } + secureViewer.setContent(dataToBeSigned); + log.trace("show secure viewer returned"); } - private void showSignedReferencesListDialog(final List signedReferences, final ActionListener backListener, final String backCommand) { + private void showSignedReferencesListDialog(final List signedReferences, + final ActionListener backListener, final String backCommand) { log.debug("scheduling signed references list dialog"); @@ -1154,7 +1288,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show signed references list dialog"); + log.debug("show signed references list dialog [" + Thread.currentThread().getName() + "]"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -1202,13 +1336,7 @@ public class BKUGUIImpl implements BKUGUIFacade { int selectionIdx = lsm.getMinSelectionIndex(); if (selectionIdx >= 0) { final HashDataInput selection = signedReferences.get(selectionIdx); - showHashDataViewer(selection, new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - showSaveHashDataInputDialog(Collections.singletonList(selection), null, null); - } - }, "save"); + showSecureViewer(selection); } } }); @@ -1255,9 +1383,8 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonPanel.setLayout(buttonPanelLayout); buttonPanelLayout.setHorizontalGroup(buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup(buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + buttonPanelLayout.setVerticalGroup(buttonPanelLayout.createSequentialGroup() .addComponent(backButton)); contentPanel.validate(); @@ -1266,96 +1393,101 @@ public class BKUGUIImpl implements BKUGUIFacade { } /** - * - * @param signedRefs * @param okListener may be null - * @param okCommand */ - private void showSaveHashDataInputDialog(final List signedRefs, final ActionListener okListener, final String okCommand) { - - log.debug("scheduling save hashdatainput dialog"); - - SwingUtilities.invokeLater(new Runnable() { +// private void showSaveDialog(final List signedRefs, +// final ActionListener okListener, final String okCommand) { +// +// log.debug("scheduling save dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show save dialog"); +// +// String userHome = System.getProperty("user.home"); +// +// JFileChooser fileDialog = new JFileChooser(userHome); +// fileDialog.setMultiSelectionEnabled(false); +// fileDialog.setDialogType(JFileChooser.SAVE_DIALOG); +// fileDialog.setFileHidingEnabled(true); +// if (signedRefs.size() == 1) { +// fileDialog.setDialogTitle(getMessage(WINDOWTITLE_SAVE)); +// fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); +// String mimeType = signedRefs.get(0).getMimeType(); +// MimeFilter mimeFilter = new MimeFilter(mimeType, messages); +// fileDialog.setFileFilter(mimeFilter); +// String filename = getMessage(SAVE_HASHDATAINPUT_PREFIX) + MimeFilter.getExtension(mimeType); +// fileDialog.setSelectedFile(new File(userHome, filename)); +// } else { +// fileDialog.setDialogTitle(getMessage(WINDOWTITLE_SAVEDIR)); +// fileDialog.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); +// } +// +// //parent contentPane -> placed over applet +// switch (fileDialog.showSaveDialog(fileDialog)) { +// case JFileChooser.APPROVE_OPTION: +// File f = fileDialog.getSelectedFile(); +// for (HashDataInput hashDataInput : signedRefs) { +// String mimeType = hashDataInput.getMimeType(); +// String id = hashDataInput.getReferenceId(); +// File file; +// if (f.isDirectory()) { +// String filename = getMessage(SAVE_HASHDATAINPUT_PREFIX) + '_' + id + MimeFilter.getExtension(mimeType); +// file = new File(f, filename); +// } else { +// file = f; +// } +// if (file.exists()) { +// String ovrwrt = getMessage(MESSAGE_OVERWRITE); +// int overwrite = JOptionPane.showConfirmDialog(fileDialog, MessageFormat.format(ovrwrt, file), getMessage(WINDOWTITLE_OVERWRITE), JOptionPane.OK_CANCEL_OPTION); +// if (overwrite != JOptionPane.OK_OPTION) { +// continue; +// } +// } +// if (log.isDebugEnabled()) { +// log.debug("writing hashdata input " + id + " (" + mimeType + ") to file " + file); +// } +// FileOutputStream fos = null; +// try { +// fos = new FileOutputStream(file); +// BufferedOutputStream bos = new BufferedOutputStream(fos); +// InputStream hdi = hashDataInput.getHashDataInput(); +// int b; +// while ((b = hdi.read()) != -1) { +// bos.write(b); +// } +// bos.flush(); +// bos.close(); +// } catch (IOException ex) { +// log.error("Failed to write " + file + ": " + ex.getMessage()); +// showErrorDialog(ERR_WRITE_HASHDATA, new Object[] {ex.getMessage()}, null, null); +// ex.printStackTrace(); +// } finally { +// try { +// fos.close(); +// } catch (IOException ex) { +// } +// } +// } +// break; +// case JFileChooser.CANCEL_OPTION : +// log.debug("cancelled save dialog"); +// break; +// } +// if (okListener != null) { +// okListener.actionPerformed(new ActionEvent(fileDialog, ActionEvent.ACTION_PERFORMED, okCommand)); +// } +// } +// }); +// } + + //////////////////////////////////////////////////////////////////////////// + // UTILITY METHODS + //////////////////////////////////////////////////////////////////////////// - @Override - public void run() { - - log.debug("show save hashdatainput dialog"); - - String userHome = System.getProperty("user.home"); - - JFileChooser fileDialog = new JFileChooser(userHome); - fileDialog.setMultiSelectionEnabled(false); - fileDialog.setDialogType(JFileChooser.SAVE_DIALOG); - fileDialog.setFileHidingEnabled(true); - if (signedRefs.size() == 1) { - fileDialog.setDialogTitle(getMessage(WINDOWTITLE_SAVE)); - fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); - String mimeType = signedRefs.get(0).getMimeType(); - MimeFilter mimeFilter = new MimeFilter(mimeType, messages); - fileDialog.setFileFilter(mimeFilter); - String filename = getMessage(SAVE_HASHDATAINPUT_PREFIX) + MimeFilter.getExtension(mimeType); - fileDialog.setSelectedFile(new File(userHome, filename)); - } else { - fileDialog.setDialogTitle(getMessage(WINDOWTITLE_SAVEDIR)); - fileDialog.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - } - - //parent contentPane -> placed over applet - switch (fileDialog.showSaveDialog(fileDialog)) { - case JFileChooser.APPROVE_OPTION: - File f = fileDialog.getSelectedFile(); - for (HashDataInput hashDataInput : signedRefs) { - String mimeType = hashDataInput.getMimeType(); - String id = hashDataInput.getReferenceId(); - File file; - if (f.isDirectory()) { - String filename = getMessage(SAVE_HASHDATAINPUT_PREFIX) + '_' + id + MimeFilter.getExtension(mimeType); - file = new File(f, filename); - } else { - file = f; - } - if (file.exists()) { - String ovrwrt = getMessage(MESSAGE_OVERWRITE); - int overwrite = JOptionPane.showConfirmDialog(fileDialog, MessageFormat.format(ovrwrt, file), getMessage(WINDOWTITLE_OVERWRITE), JOptionPane.OK_CANCEL_OPTION); - if (overwrite != JOptionPane.OK_OPTION) { - continue; - } - } - if (log.isDebugEnabled()) { - log.debug("Writing HashDataInput " + id + " (" + mimeType + ") to file " + file); - } - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file); - BufferedOutputStream bos = new BufferedOutputStream(fos); - InputStream hdi = hashDataInput.getHashDataInput(); - int b; - while ((b = hdi.read()) != -1) { - bos.write(b); - } - bos.flush(); - bos.close(); - } catch (IOException ex) { - log.error("Failed to write HashDataInput to file " + file + ": " + ex.getMessage()); - showErrorDialog(ERR_WRITE_HASHDATA, new Object[] {ex.getMessage()}, null, null); - ex.printStackTrace(); - } finally { - try { - fos.close(); - } catch (IOException ex) { - } - } - } - } - log.debug("done saving hashdatainput"); - if (okListener != null) { - okListener.actionPerformed(new ActionEvent(fileDialog, ActionEvent.ACTION_PERFORMED, okCommand)); - } - } - }); - } - private void registerHelpListener(ActionListener helpListener) { if (helpListener != null) { this.helpListener = new HelpMouseListener(helpListener); @@ -1371,6 +1503,11 @@ public class BKUGUIImpl implements BKUGUIFacade { } } + + //////////////////////////////////////////////////////////////////////////// + // INITIALIZERS (MAY BE OVERRIDDEN BY SUBCLASSES) + //////////////////////////////////////////////////////////////////////////// + /** * Called from constructor. * Subclasses may override this method to ensure the message bundle is loaded diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java deleted file mode 100644 index 6c097b2a..00000000 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * 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 at.gv.egiz.bku.gui; - -import at.gv.egiz.bku.gui.html.RestrictedHTMLEditorKit; -import at.gv.egiz.stal.HashDataInput; -import java.awt.Component; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.Charset; -import java.text.MessageFormat; -import java.util.ResourceBundle; -import javax.swing.GroupLayout; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JEditorPane; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.LayoutStyle; -import javax.swing.text.Document; -import javax.swing.text.EditorKit; -import javax.swing.text.StyledEditorKit; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author Clemens Orthacker - */ -public class HashDataViewer extends JDialog - implements ActionListener { - - public static final String PLAINTEXT_FONT = "Monospaced"; - protected static final Log log = LogFactory.getLog(HashDataViewer.class); - - private static HashDataViewer dialog; - - protected ResourceBundle messages; - - /** - * - * @param signedReferences currently, only one hashdata input (the first in the list) is displayed - */ - public static void showHashDataInput(HashDataInput hashDataInput, - ResourceBundle messages, - ActionListener saveListener, - String saveCommand, - ActionListener helpListener) { - showHashDataInput(null, hashDataInput, messages, saveListener, saveCommand, helpListener); - } - - /** - * - * @param frameComp owner - */ - public static void showHashDataInput(Component frameComp, - HashDataInput hashDataInput, - ResourceBundle messages, - ActionListener saveListener, - String saveCommand, - ActionListener helpListener) { - - Frame frame = null; - if (frameComp != null) { - JOptionPane.getFrameForComponent(frameComp); - } - dialog = new HashDataViewer(frame, - messages, - hashDataInput, - saveListener, - saveCommand, - helpListener); - dialog.setVisible(true); - } - - private HashDataViewer(Frame frame, - ResourceBundle messages, - HashDataInput hashDataInput, - ActionListener saveListener, - String saveCommand, - ActionListener helpListener) { - super(frame, messages.getString(BKUGUIFacade.WINDOWTITLE_VIEWER), true); - this.messages = messages; - - Charset cs; - if (hashDataInput.getEncoding() == null) { - cs = Charset.forName("UTF-8"); - } else { - try { - cs = Charset.forName(hashDataInput.getEncoding()); - } catch (Exception ex) { - log.debug("charset " + hashDataInput.getEncoding() + " not supported, assuming UTF-8: " + ex.getMessage()); - cs = Charset.forName("UTF-8"); - } - } - - - InputStreamReader isr = new InputStreamReader(hashDataInput.getHashDataInput(), cs); - Reader content = new BufferedReader(isr); - - JPanel hashDataPanel = createViewerPanel(content, - hashDataInput.getMimeType(), - helpListener); - JPanel buttonPanel = createButtonPanel(saveListener, saveCommand); - initContentPane(new Dimension(600, 400), hashDataPanel, buttonPanel); - - pack(); - if (frame != null) { - setLocationRelativeTo(frame); - } else { - setLocationByPlatform(true); - } - } - - private void initContentPane(Dimension preferredSize, JPanel viewerPanel, JPanel buttonPanel) { - Container contentPane = getContentPane(); - contentPane.setPreferredSize(preferredSize); - - GroupLayout mainLayout = new GroupLayout(contentPane); - contentPane.setLayout(mainLayout); - - mainLayout.setHorizontalGroup( - mainLayout.createSequentialGroup().addContainerGap().addGroup( - mainLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)).addContainerGap()); - mainLayout.setVerticalGroup( - mainLayout.createSequentialGroup() - .addContainerGap() - .addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(buttonPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap()); - } - - /** - * - * @param messages - * @param content - * @param mimeType defaults to text/plain if null - * @param encoding must be null if document contains charset declaration (e.g. HTML page), otherwise the parser crashes - * @param helpListener may be null - * @return - */ - private JPanel createViewerPanel(Reader content, - String mimeType, - final ActionListener helpListener) { - - if (mimeType == null) { - mimeType = "text/plain"; - } - log.debug("viewer dialog: " + mimeType); - - JEditorPane viewer = new JEditorPane(); - viewer.setEditable(false); - viewer.setContentType(mimeType); - - if ("text/plain".equals(mimeType)) { - viewer.setEditorKit(new StyledEditorKit()); - viewer.setFont(new Font(PLAINTEXT_FONT, viewer.getFont().getStyle(), viewer.getFont().getSize())); -// } else if ("text/html".equals(mimeType)) { -// viewer.setEditorKit(new RestrictedHTMLEditorKit()); - } else if ("application/xhtml+xml".equals(mimeType)) { - viewer.setContentType("text/html"); - } - - EditorKit editorKit = viewer.getEditorKit(); - Document document = editorKit.createDefaultDocument(); -// document.putProperty("IgnoreCharsetDirective", new Boolean(true)); - - try { - viewer.read(content, document); - content.close(); - } catch (Exception ex) { - log.error(ex.getMessage(), ex); - String p = messages.getString(BKUGUIFacade.ERR_VIEWER); - viewer.setText(MessageFormat.format(p, ex.getMessage())); - } - - JScrollPane scrollPane = new JScrollPane(viewer); - scrollPane.setPreferredSize(viewer.getPreferredSize()); - scrollPane.setAlignmentX(LEFT_ALIGNMENT); - viewer.setCaretPosition(0); - - JPanel viewerPanel = new JPanel(); - GroupLayout viewerPanelLayout = new GroupLayout(viewerPanel); - viewerPanel.setLayout(viewerPanelLayout); - - GroupLayout.SequentialGroup infoHorizontal = viewerPanelLayout.createSequentialGroup(); - GroupLayout.ParallelGroup infoVertical = viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); - - if ("application/xhtml+xml".equals(mimeType)) { - JLabel viewerLabel = new JLabel(); - viewerLabel.setText(messages.getString(BKUGUIFacade.WARNING_XHTML)); - viewerLabel.setFont(viewerLabel.getFont().deriveFont(viewerLabel.getFont().getStyle() | java.awt.Font.BOLD)); - viewerLabel.setLabelFor(viewer); - - infoHorizontal.addComponent(viewerLabel); - infoVertical.addComponent(viewerLabel); - } - - if (helpListener != null) { - JLabel helpLabel = new JLabel(); - helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG))); - helpLabel.getAccessibleContext().setAccessibleName(messages.getString(BKUGUIFacade.ALT_HELP)); - helpLabel.addMouseListener(new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent arg0) { - ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, BKUGUIFacade.HELP_HASHDATAVIEWER); - helpListener.actionPerformed(e); - } - }); - helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - - infoHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - infoVertical - .addComponent(helpLabel); - } - - viewerPanelLayout.setHorizontalGroup( - viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(infoHorizontal) - .addComponent(scrollPane)); - viewerPanelLayout.setVerticalGroup( - viewerPanelLayout.createSequentialGroup() - .addGroup(infoVertical) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(scrollPane)); - - - return viewerPanel; - } - - private JPanel createButtonPanel(ActionListener saveListener, String saveCommand) { - JButton closeButton = new JButton(); - closeButton.setText(messages.getString(BKUGUIFacade.BUTTON_CLOSE)); - closeButton.addActionListener(this); - - JButton saveButton = new JButton(); - saveButton.setText(messages.getString(BKUGUIFacade.BUTTON_SAVE)); - saveButton.setActionCommand(saveCommand); - saveButton.addActionListener(saveListener); - - int buttonSize = closeButton.getPreferredSize().width; - if (saveButton.getPreferredSize().width > buttonSize) { - buttonSize = saveButton.getPreferredSize().width; - } - - JPanel buttonPanel = new JPanel(); - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup().addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(closeButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(saveButton).addComponent(closeButton)); - - return buttonPanel; - } - - @Override - public void actionPerformed(ActionEvent e) { - HashDataViewer.dialog.setVisible(false); - } -} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java new file mode 100644 index 00000000..6a16306b --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java @@ -0,0 +1,371 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.gui; + +import at.gv.egiz.stal.HashDataInput; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.Charset; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import javax.swing.GroupLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JEditorPane; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.LayoutStyle; +import javax.swing.SwingUtilities; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; +import javax.swing.text.StyledEditorKit; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public class SecureViewerDialog extends JDialog implements ActionListener { + + public static final String PLAINTEXT_FONT = "Monospaced"; + public static final Dimension VIEWER_DIMENSION = new Dimension(600, 400); + protected static final Log log = LogFactory.getLog(SecureViewerDialog.class); + +// private static SecureViewerDialog dialog; + protected ResourceBundle messages; + protected JEditorPane viewer; + protected JLabel viewerLabel; + protected JScrollPane scrollPane; + protected HashDataInput content; //remember for save dialog + + /** + * Create and display a modal SecureViewer dialog. + * This method blocks until the dialog's close button is pressed. + * + * @param owner, dialog is positioned relative to its owner + * (if null, at default location of native windowing system) + */ +// public static void showDataToBeSigned(HashDataInput dataToBeSigned, +// ResourceBundle messages, +// ActionListener saveListener, String saveCommand, +// ActionListener helpListener) { +// +//// Frame ownerFrame = (owner != null) ? +//// JOptionPane.getFrameForComponent(owner) : +//// null; +// dialog = new SecureViewerDialog(null, messages, +// saveListener, saveCommand, helpListener); +// dialog.setContent(dataToBeSigned); +// dialog.setVisible(true); +// } + public SecureViewerDialog(Frame owner, ResourceBundle messages, +// ActionListener saveListener, String saveCommand, + ActionListener helpListener) { + super(owner, messages.getString(BKUGUIFacade.WINDOWTITLE_VIEWER), true); + this.messages = messages; + + initContentPane(VIEWER_DIMENSION, + createViewerPanel(helpListener), + createButtonPanel()); //saveListener, saveCommand)); + + pack(); + if (owner != null) { + setLocationRelativeTo(owner); + } else { + setLocationByPlatform(true); + } + } + + private void initContentPane(Dimension preferredSize, + JPanel viewerPanel, JPanel buttonPanel) { + Container contentPane = getContentPane(); + contentPane.setPreferredSize(preferredSize); + + GroupLayout mainLayout = new GroupLayout(contentPane); + contentPane.setLayout(mainLayout); + + mainLayout.setHorizontalGroup( + mainLayout.createSequentialGroup().addContainerGap().addGroup( + mainLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)).addContainerGap()); + mainLayout.setVerticalGroup( + mainLayout.createSequentialGroup().addContainerGap().addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED).addComponent(buttonPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addContainerGap()); + } + + /** + * @param helpListener may be null + */ + private JPanel createViewerPanel(final ActionListener helpListener) { + viewer = new JEditorPane(); + viewer.setEditable(false); + + scrollPane = new JScrollPane(); + + JPanel viewerPanel = new JPanel(); + GroupLayout viewerPanelLayout = new GroupLayout(viewerPanel); + viewerPanel.setLayout(viewerPanelLayout); + + GroupLayout.SequentialGroup infoHorizontal = viewerPanelLayout.createSequentialGroup(); + GroupLayout.ParallelGroup infoVertical = viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + + viewerLabel = new JLabel(); + viewerLabel.setFont(viewerLabel.getFont().deriveFont(viewerLabel.getFont().getStyle() | java.awt.Font.BOLD)); +// viewerLabel.setLabelFor(viewer); + + infoHorizontal.addComponent(viewerLabel); + infoVertical.addComponent(viewerLabel); + + if (helpListener != null) { + JLabel helpLabel = new JLabel(); + helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG))); + helpLabel.getAccessibleContext().setAccessibleName(messages.getString(BKUGUIFacade.ALT_HELP)); + helpLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent arg0) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, BKUGUIFacade.HELP_HASHDATAVIEWER); + helpListener.actionPerformed(e); + } + }); + helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + + infoHorizontal.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE).addComponent(helpLabel); + infoVertical.addComponent(helpLabel); + } + + viewerPanelLayout.setHorizontalGroup( + viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(infoHorizontal).addComponent(scrollPane)); + viewerPanelLayout.setVerticalGroup( + viewerPanelLayout.createSequentialGroup().addGroup(infoVertical).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(scrollPane)); + + return viewerPanel; + } + + /** + * Sets the hashdataInput to be displayed and makes the dialog visible. + * This method blocks until the dialog's close button is pressed. + * + * @param mimeType defaults to text/plain if null + * @param encoding must be null if document contains charset declaration (e.g. HTML page), otherwise the parser crashes + + * @param hashDataInput + */ + public void setContent(HashDataInput hashDataInput) { + + this.content = null; + + String mimeType = hashDataInput.getMimeType(); + if (mimeType == null) { + mimeType = "text/plain"; + } + log.debug("secure viewer mime type: " + mimeType); + // loads editorkit for text/plain if unrecognized + viewer.setContentType(mimeType); + + if ("text/plain".equals(mimeType)) { + viewer.setEditorKit(new StyledEditorKit()); + viewer.setFont(new Font(PLAINTEXT_FONT, viewer.getFont().getStyle(), viewer.getFont().getSize())); +// } else if ("text/html".equals(mimeType)) { +// viewer.setEditorKit(new RestrictedHTMLEditorKit()); + } else if ("application/xhtml+xml".equals(mimeType)) { + viewer.setContentType("text/html"); + } + + EditorKit editorKit = viewer.getEditorKit(); + Document document = editorKit.createDefaultDocument(); +// document.putProperty("IgnoreCharsetDirective", new Boolean(true)); + + try { + Charset cs = (hashDataInput.getEncoding() == null) ? Charset.forName("UTF-8") : Charset.forName(hashDataInput.getEncoding()); + log.debug("secure viewer encoding: " + cs.toString()); + + InputStreamReader isr = new InputStreamReader(hashDataInput.getHashDataInput(), cs); + Reader contentReader = new BufferedReader(isr); + viewer.read(contentReader, document); + contentReader.close(); + + this.content = hashDataInput; + +// } catch (IllegalCharsetNameException ex) { +// } catch (UnsupportedCharsetException ex) { + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + String p = messages.getString(BKUGUIFacade.ERR_VIEWER); + viewer.setText(MessageFormat.format(p, ex.getMessage())); + } + viewer.setCaretPosition(0); + + scrollPane.setViewportView(viewer); + scrollPane.setPreferredSize(viewer.getPreferredSize()); + scrollPane.setAlignmentX(LEFT_ALIGNMENT); + + if ("application/xhtml+xml".equals(mimeType)) { + viewerLabel.setText(messages.getString(BKUGUIFacade.WARNING_XHTML)); + } else { + viewerLabel.setText(""); + } + + setVisible(true); + } + + private JPanel createButtonPanel() { //ActionListener saveListener, String saveCommand) { + JButton closeButton = new JButton(); + closeButton.setText(messages.getString(BKUGUIFacade.BUTTON_CLOSE)); + closeButton.setActionCommand("close"); + closeButton.addActionListener(this); + + JButton saveButton = new JButton(); + saveButton.setText(messages.getString(BKUGUIFacade.BUTTON_SAVE)); + saveButton.setActionCommand("save"); + saveButton.addActionListener(this); + + int buttonSize = closeButton.getPreferredSize().width; + if (saveButton.getPreferredSize().width > buttonSize) { + buttonSize = saveButton.getPreferredSize().width; + } + + JPanel buttonPanel = new JPanel(); + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + buttonPanelLayout.setHorizontalGroup( + buttonPanelLayout.createSequentialGroup().addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(closeButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); + buttonPanelLayout.setVerticalGroup( + buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(saveButton).addComponent(closeButton)); + + return buttonPanel; + } + + @Override + public void actionPerformed(ActionEvent e) { + if ("close".equals(e.getActionCommand())) { +// SecureViewerDialog.dialog.setVisible(false); + log.trace("closing secure viewer"); + setVisible(false); + log.trace("secure viewer closed"); + } else if ("save".equals(e.getActionCommand())) { + log.trace("display secure viewer save dialog"); + showSaveDialog(content, null, null); + log.trace("done secure viewer save"); + } else { + log.warn("unknown action command " + e.getActionCommand()); + } + } + + private void showSaveDialog(final HashDataInput hashDataInput, + final ActionListener okListener, final String okCommand) { + + log.debug("scheduling save dialog [" + Thread.currentThread().getName() + "]"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("show save dialog [" + Thread.currentThread().getName() + "]"); + + String userHome = System.getProperty("user.home"); + + JFileChooser fileDialog = new JFileChooser(userHome); + fileDialog.setMultiSelectionEnabled(false); + fileDialog.setDialogType(JFileChooser.SAVE_DIALOG); + fileDialog.setFileHidingEnabled(true); + fileDialog.setDialogTitle(messages.getString(BKUGUIFacade.WINDOWTITLE_SAVE)); + fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); + String mimeType = hashDataInput.getMimeType(); + MimeFilter mimeFilter = new MimeFilter(mimeType, messages); + fileDialog.setFileFilter(mimeFilter); + String filename = messages.getString(BKUGUIFacade.SAVE_HASHDATAINPUT_PREFIX) + + MimeFilter.getExtension(mimeType); + fileDialog.setSelectedFile(new File(userHome, filename)); + + //parent contentPane -> placed over applet + switch (fileDialog.showSaveDialog(fileDialog)) { + case JFileChooser.APPROVE_OPTION: + File file = fileDialog.getSelectedFile(); + String id = hashDataInput.getReferenceId(); + if (file.exists()) { + String msgPattern = messages.getString(BKUGUIFacade.MESSAGE_OVERWRITE); + int overwrite = JOptionPane.showConfirmDialog(fileDialog, + MessageFormat.format(msgPattern, file), + messages.getString(BKUGUIFacade.WINDOWTITLE_OVERWRITE), + JOptionPane.OK_CANCEL_OPTION); + if (overwrite != JOptionPane.OK_OPTION) { + return; + } + } + if (log.isDebugEnabled()) { + log.debug("writing hashdata input " + id + " (" + mimeType + ") to file " + file); + } + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file); + BufferedOutputStream bos = new BufferedOutputStream(fos); + InputStream hdi = hashDataInput.getHashDataInput(); + int b; + while ((b = hdi.read()) != -1) { + bos.write(b); + } + bos.flush(); + bos.close(); + } catch (IOException ex) { + log.error("Failed to write " + file + ": " + ex.getMessage()); + log.debug(ex); + String errPattern = messages.getString(BKUGUIFacade.ERR_WRITE_HASHDATA); + JOptionPane.showMessageDialog(fileDialog, + MessageFormat.format(errPattern, ex.getMessage()), + messages.getString(BKUGUIFacade.WINDOWTITLE_ERROR), + JOptionPane.ERROR_MESSAGE); + } finally { + try { + if (fos != null) { + fos.close(); + } + } catch (IOException ex) { + } + } + break; + case JFileChooser.CANCEL_OPTION: + log.debug("cancelled save dialog"); + break; + } + if (okListener != null) { + okListener.actionPerformed(new ActionEvent(fileDialog, ActionEvent.ACTION_PERFORMED, okCommand)); + } + } + }); + } +} diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 6d651b2d..9bfe8fb1 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -25,6 +25,7 @@ title.retry=Falsche PIN title.wait=Bitte warten title.hashdata=Signaturdaten windowtitle.save=Signaturdaten speichern +windowtitle.error=Fehler windowtitle.savedir=Signaturdaten in Verzeichnis speichern windowtitle.overwrite=Datei \u00FCberschreiben? windowtitle.viewer=Signaturdaten @@ -79,7 +80,7 @@ error.unknown.param=Ein Fehler trat auf: {0} error.unknown=Ein Fehler trat auf error.test=Fehler1 {0} - Fehler2 {1} error.card.locked=B\u00FCrgerkarte ist gesperrt -error.card.notactivated=B\u00FCrgerkartenfunktion ist nicht aktiviert +error.card.notactivated=Die B\u00FCrgerkarte ist nicht aktiviert error.pin.timeout=Zeit\u00FCberschreitung bei Eingabe der PIN error.viewer=Der Inhalt kann nicht dargestellt werden: {0} error.external.link=Externer Link {0} wird nicht ge\u00F6ffnet diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties index 2fb66969..a36f9b83 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties @@ -25,6 +25,7 @@ title.retry=Wrong PIN title.wait=Please wait title.hashdata=Signature data windowtitle.save=Save signature data +windowtitle.error=Error windowtitle.savedir=Save signature data to directory windowtitle.overwrite=Overwrite file? windowtitle.viewer=Signature data diff --git a/BKUCommonGUI/src/main/resources/images/ChipperlingLogo.png b/BKUCommonGUI/src/main/resources/images/ChipperlingLogo.png new file mode 100644 index 00000000..eee4be4f Binary files /dev/null and b/BKUCommonGUI/src/main/resources/images/ChipperlingLogo.png differ diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java index c8cff617..b3eaf8c7 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java @@ -39,8 +39,9 @@ public class BKUGUITest { public void testBKUGUI() { JFrame testFrame = new JFrame("BKUGUITest"); Container contentPane = testFrame.getContentPane(); - contentPane.setPreferredSize(new Dimension(170, 150)); - BKUGUIFacade gui = new BKUGUIImpl(contentPane, null, BKUGUIFacade.Style.tiny, null, null); +// contentPane.setPreferredSize(new Dimension(170, 150)); + contentPane.setPreferredSize(new Dimension(290, 190)); + BKUGUIFacade gui = new BKUGUIImpl(contentPane, null, BKUGUIFacade.Style.advanced, null, null); BKUGUIWorker worker = new BKUGUIWorker(); worker.init(gui); testFrame.pack(); diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index 194e18b0..5475a45b 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -149,7 +149,9 @@ public class BKUGUIWorker implements Runnable { // // Thread.sleep(2000); // - gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); +// gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); + + gui.showPinpadSignaturePINDialog(signPinSpec, -1, hashdataListener, "hashdata"); // // Thread.sleep(4000); // diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java index 5a0ba84a..3f560967 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java @@ -144,4 +144,12 @@ public class BKUGuiProxy implements BKUGUIFacade { showDialog(); delegate.showMessageDialog(titleKey, msgKey); } + + @Override + public void showPinpadSignaturePINDialog(PINSpec pinSpec, int numRetries, + ActionListener viewerListener, String viewerCommand) { + showDialog(); + delegate.showPinpadSignaturePINDialog(pinSpec, numRetries, + viewerListener, viewerCommand); + } } diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java index 61cc7c4c..a782de1a 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java @@ -37,7 +37,8 @@ public class LocalBKUWorker extends AbstractBKUWorker { public LocalBKUWorker(BKUGUIFacade gui, JDialog container) { super(gui); this.container = container; - addRequestHandler(SignRequest.class, new LocalSignRequestHandler()); + addRequestHandler(SignRequest.class, + new LocalSignRequestHandler(new LocalSecureViewer(gui))); } @Override diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSecureViewer.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSecureViewer.java new file mode 100644 index 00000000..cbe5af7a --- /dev/null +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSecureViewer.java @@ -0,0 +1,109 @@ + +package at.gv.egiz.bku.local.stal; + +import at.gv.egiz.bku.slcommands.impl.DataObjectHashDataInput; +import at.gv.egiz.bku.smccstal.SecureViewer; +import java.io.IOException; +import java.util.ArrayList; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; +import at.gv.egiz.stal.signedinfo.ReferenceType; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.awt.event.ActionListener; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.Collections; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class LocalSecureViewer implements SecureViewer { + + private static final Log log = LogFactory.getLog(LocalSignRequestHandler.class); + private List hashDataInputs = Collections.EMPTY_LIST; + + protected BKUGUIFacade gui; + + public LocalSecureViewer(BKUGUIFacade gui) { + this.gui = gui; + } + + public void setDataToBeSigned(List dataToBeSigned) { + this.hashDataInputs = dataToBeSigned; + } + + /** + * + * @param dsigReferences + * @throws java.lang.Exception + */ + @Override + public void displayDataToBeSigned(SignedInfoType signedInfo, + ActionListener okListener, String okCommand) + throws Exception { + if (signedInfo.getReference().size() == 0) { + log.error("No hashdata input selected to be displayed: null"); + throw new Exception("No HashData Input selected to be displayed"); + } + + ArrayList selectedHashDataInputs = new ArrayList(); + for (ReferenceType dsigRef : signedInfo.getReference()) { + // don't get Manifest, QualifyingProperties, ... + if (dsigRef.getType() == null) { + String dsigRefId = dsigRef.getId(); + if (dsigRefId != null) { + boolean hdiAvailable = false; + for (HashDataInput hashDataInput : hashDataInputs) { + if (dsigRefId.equals(hashDataInput.getReferenceId())) { + log.debug("display hashdata input for dsig:SignedReference " + + dsigRefId); + selectedHashDataInputs.add( + ensureCachedHashDataInput(hashDataInput)); + hdiAvailable = true; + break; + } + } + if (!hdiAvailable) { + log.error("no hashdata input for dsig:SignedReference " + dsigRefId); + throw new Exception( + "No HashDataInput available for dsig:SignedReference " + dsigRefId); + } + } else { + throw new Exception( + "Cannot get HashDataInput for dsig:Reference without Id attribute"); + } + } + } + + if (selectedHashDataInputs.size() < 1) { + log.error("dsig:SignedInfo does not contain a data reference"); + throw new Exception("dsig:SignedInfo does not contain a data reference"); + } + gui.showSecureViewer(selectedHashDataInputs, okListener, okCommand); + } + + + private HashDataInput ensureCachedHashDataInput(HashDataInput hashDataInput) + throws IOException { + if (!(hashDataInput instanceof DataObjectHashDataInput)) { + + log.warn("expected DataObjectHashDataInput for LocalSignRequestHandler, got " + + hashDataInput.getClass().getName()); + + InputStream hdIs = hashDataInput.getHashDataInput(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(hdIs.available()); + int b; + while ((b = hdIs.read()) != -1) { + baos.write(b); + } + hashDataInput = new ByteArrayHashDataInput(baos.toByteArray(), + hashDataInput.getReferenceId(), + hashDataInput.getMimeType(), + hashDataInput.getEncoding()); + } + return hashDataInput; + } + +} diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java index 531e6591..492b8a05 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java @@ -16,9 +16,7 @@ */ package at.gv.egiz.bku.local.stal; -import at.gv.egiz.bku.slcommands.impl.DataObjectHashDataInput; -import java.io.IOException; -import java.util.ArrayList; +import at.gv.egiz.bku.smccstal.SecureViewer; import java.util.Collections; import java.util.List; @@ -40,9 +38,16 @@ import java.io.InputStream; * @author clemens */ public class LocalSignRequestHandler extends SignRequestHandler { +// implements SecureViewer { private static final Log log = LogFactory.getLog(LocalSignRequestHandler.class); - private List hashDataInputs = Collections.EMPTY_LIST; + + protected LocalSecureViewer secureViewer; + + public LocalSignRequestHandler(LocalSecureViewer secureViewer) { + super(secureViewer); + } + /** * If the request is a SIGN request, it contains a list of DataObjectHashDataInput @@ -53,75 +58,13 @@ public class LocalSignRequestHandler extends SignRequestHandler { */ @SuppressWarnings("unchecked") @Override - public STALResponse handleRequest(STALRequest request) throws InterruptedException { + public STALResponse handleRequest(STALRequest request) + throws InterruptedException { + if (request instanceof SignRequest) { SignRequest signReq = (SignRequest) request; - hashDataInputs = signReq.getHashDataInput(); + secureViewer.setDataToBeSigned(signReq.getHashDataInput()); } return super.handleRequest(request); } - - /** - * - * @param dsigReferences - * @throws java.lang.Exception - */ - @Override - public void displayDataToBeSigned(List dsigReferences) throws Exception { - if (dsigReferences == null || dsigReferences.size() < 1) { - log.error("No hashdata input selected to be displayed: null"); - throw new Exception("No HashData Input selected to be displayed"); - } - - ArrayList selectedHashDataInputs = new ArrayList(); - for (ReferenceType dsigRef : dsigReferences) { - // don't get Manifest, QualifyingProperties, ... - if (dsigRef.getType() == null) { - String dsigRefId = dsigRef.getId(); - if (dsigRefId != null) { - boolean hdiAvailable = false; - for (HashDataInput hashDataInput : hashDataInputs) { - if (dsigRefId.equals(hashDataInput.getReferenceId())) { - log.debug("display hashdata input for dsig:SignedReference " + dsigRefId); - if (!(hashDataInput instanceof DataObjectHashDataInput)) { - log.warn( - "expected DataObjectHashDataInput for LocalSignRequestHandler, got " + hashDataInput.getClass().getName()); - hashDataInput = getByteArrayHashDataInput(hashDataInput); - } - selectedHashDataInputs.add(hashDataInput); - hdiAvailable = true; - break; - } - } - if (!hdiAvailable) { - log.error("no hashdata input for dsig:SignedReference " + dsigRefId); - throw new Exception( - "No HashDataInput available for dsig:SignedReference " + dsigRefId); - } - } else { - throw new Exception( - "Cannot get HashDataInput for dsig:Reference without Id attribute"); - } - } - } - - if (selectedHashDataInputs.size() < 1) { - log.error("dsig:SignedInfo does not contain a data reference"); - throw new Exception("dsig:SignedInfo does not contain a data reference"); - } - gui.showSecureViewer(selectedHashDataInputs, this, "hashDataDone"); - } - - private ByteArrayHashDataInput getByteArrayHashDataInput(HashDataInput hashDataInput) throws IOException { - - InputStream hdIs = hashDataInput.getHashDataInput(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(hdIs.available()); - int b; - while ((b = hdIs.read()) != -1) { - baos.write(b); - } - ByteArrayHashDataInput hdi = new ByteArrayHashDataInput(baos.toByteArray(), hashDataInput.getReferenceId(), hashDataInput.getMimeType(), hashDataInput.getEncoding()); - - return hdi; - } } diff --git a/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties b/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties index e2f07481..04c9c7bf 100644 --- a/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties +++ b/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties @@ -40,9 +40,12 @@ SSL.sslProtocol=TLS # warning do not set the following property to true # its intended for debugging and testing only SSL.disableAllChecks=false +#SSL.disableHostnameVerification=true # ------------ END SSL Config -------------------- +#UserAgent=citizen-card-environment/1.2 MOCCA/1.0 + ValidateHashDataInputs=true AppletTimeout=300000 diff --git a/BKUOnline/src/main/resources/log4j.properties b/BKUOnline/src/main/resources/log4j.properties index f608c83d..25ea9faa 100644 --- a/BKUOnline/src/main/resources/log4j.properties +++ b/BKUOnline/src/main/resources/log4j.properties @@ -30,7 +30,7 @@ log4j.appender.STDOUT.layout.ConversionPattern=%-5p | %t | %c %x - %m%n log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.maxFileSize=500KB log4j.appender.file.maxBackupIndex=9 -log4j.appender.file.File=${catalina.home}/logs/bkuonline.log +log4j.appender.file.File=${catalina.base}/logs/bkuonline.log log4j.appender.file.threshold=trace log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p | %t | %c{1}:%L - %m%n \ No newline at end of file diff --git a/BKUOnline/src/main/webapp/SLRequestForm.html b/BKUOnline/src/main/webapp/SLRequestForm.html index 9ff7b68a..4714e82f 100644 --- a/BKUOnline/src/main/webapp/SLRequestForm.html +++ b/BKUOnline/src/main/webapp/SLRequestForm.html @@ -103,6 +103,33 @@ --> + - + + + PINManagementServlet + /PINManagement + index.html index.htm diff --git a/BKULocal/src/main/webapp/index.html b/BKULocal/src/main/webapp/index.html index 215eec80..537c154a 100644 --- a/BKULocal/src/main/webapp/index.html +++ b/BKULocal/src/main/webapp/index.html @@ -23,7 +23,12 @@

BKU Web Start - Willkommen

-

Diese Seite installiert das MOCCA Zertifikat in ihrem Browser. +

+

Diese Seite installiert das MOCCA Zertifikat in ihrem Browser. In jedem weiteren Browser können sie dieses durch Aufruf dieser Seite ebenso installieren.

+
+ diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java index 23d832a2..ca40ddc0 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java @@ -1,10 +1,10 @@ package at.gv.egiz.bku.webstart; +import at.gv.egiz.bku.webstart.gui.AboutDialog; import at.gv.egiz.bku.webstart.gui.BKUControllerInterface; -import at.gv.egiz.bku.webstart.gui.TrayMenuListener; +import at.gv.egiz.bku.webstart.gui.PINManagementInvoker; import iaik.asn1.CodingException; import java.io.IOException; -import java.net.URISyntaxException; import java.util.Locale; import java.util.ResourceBundle; @@ -21,8 +21,12 @@ import java.awt.PopupMenu; import java.awt.SplashScreen; import java.awt.SystemTray; import java.awt.TrayIcon; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; import java.net.BindException; -import java.net.URI; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; import java.net.URL; import java.security.GeneralSecurityException; import java.util.jar.Attributes; @@ -30,9 +34,10 @@ import java.util.jar.Manifest; import javax.imageio.ImageIO; import javax.jnlp.BasicService; import javax.jnlp.ServiceManager; +import javax.swing.JFrame; import org.mortbay.util.MultiException; -public class Launcher implements BKUControllerInterface { +public class Launcher implements BKUControllerInterface, ActionListener { public static final String WEBAPP_RESOURCE = "BKULocal.war"; public static final String CERTIFICATES_RESOURCE = "BKUCertificates.jar"; @@ -51,23 +56,37 @@ public class Launcher implements BKUControllerInterface { public static final String ERROR_START = "tray.error.start"; public static final String ERROR_CONFIG = "tray.error.config"; public static final String ERROR_BIND = "tray.error.bind"; + public static final String ERROR_PIN = "tray.error.pin.connect"; public static final String LABEL_SHUTDOWN = "tray.label.shutdown"; public static final String LABEL_PIN = "tray.label.pin"; public static final String LABEL_ABOUT = "tray.label.about"; public static final String TOOLTIP_DEFAULT = "tray.tooltip.default"; - - /** local bku uri */ - public static final URI HTTPS_SECURITY_LAYER_URI; + + /** action commands for tray menu */ + public static final String SHUTDOWN_COMMAND = "shutdown"; + public static final String PIN_COMMAND = "pin"; + public static final String ABOUT_COMMAND = "about"; + private static Log log = LogFactory.getLog(Launcher.class); + /** local bku uri */ + public static final URL HTTP_SECURITY_LAYER_URL; + public static final URL HTTPS_SECURITY_LAYER_URL; + public static final URL PIN_MANAGEMENT_URL; static { - URI tmp = null; + URL http = null; + URL https = null; + URL pin = null; try { - tmp = new URI("https://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3496).intValue()); - } catch (URISyntaxException ex) { + http = new URL("http://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3495).intValue()); + https = new URL("https://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3496).intValue()); + pin = new URL(http, "/PINManagement"); + } catch (MalformedURLException ex) { log.error(ex); } finally { - HTTPS_SECURITY_LAYER_URI = tmp; + HTTP_SECURITY_LAYER_URL = http; + HTTPS_SECURITY_LAYER_URL = https; + PIN_MANAGEMENT_URL = pin; } } public static final String version; @@ -96,6 +115,8 @@ public class Launcher implements BKUControllerInterface { private BasicService basicService; private TrayIcon trayIcon; private ResourceBundle messages; + private AboutDialog aboutDialog; + public Launcher() { if (log.isTraceEnabled()) { @@ -144,7 +165,7 @@ public class Launcher implements BKUControllerInterface { } } - private TrayIcon initTrayIcon() { //ResourceBundle messages, BKUControllerInterface bkuHook) { + private TrayIcon initTrayIcon() { if (SystemTray.isSupported()) { try { // get the SystemTray instance @@ -155,21 +176,27 @@ public class Launcher implements BKUControllerInterface { : TRAYICON_RESOURCE + "32.png"; Image image = ImageIO.read(Launcher.class.getClassLoader().getResourceAsStream(iconResource)); - TrayMenuListener listener = new TrayMenuListener(this, messages, version); PopupMenu popup = new PopupMenu(); + MenuItem pinItem = new MenuItem(messages.getString(LABEL_PIN)); + pinItem.addActionListener(this); + pinItem.setActionCommand(PIN_COMMAND); + popup.add(pinItem); + MenuItem shutdownItem = new MenuItem(messages.getString(LABEL_SHUTDOWN)); - shutdownItem.addActionListener(listener); - shutdownItem.setActionCommand(TrayMenuListener.SHUTDOWN_COMMAND); + shutdownItem.addActionListener(this); + shutdownItem.setActionCommand(SHUTDOWN_COMMAND); popup.add(shutdownItem); + popup.addSeparator(); + MenuItem aboutItem = new MenuItem(messages.getString(LABEL_ABOUT)); - aboutItem.setActionCommand(TrayMenuListener.ABOUT_COMMAND); - aboutItem.addActionListener(listener); + aboutItem.setActionCommand(ABOUT_COMMAND); + aboutItem.addActionListener(this); popup.add(aboutItem); TrayIcon ti = new TrayIcon(image, messages.getString(TOOLTIP_DEFAULT), popup); - ti.addActionListener(listener); + ti.addActionListener(this); tray.add(ti); return ti; } catch (AWTException ex) { @@ -237,15 +264,15 @@ public class Launcher implements BKUControllerInterface { Desktop desktop = Desktop.getDesktop(); if (desktop.isSupported(Desktop.Action.BROWSE)) { try { - desktop.browse(HTTPS_SECURITY_LAYER_URI); + desktop.browse(HTTPS_SECURITY_LAYER_URL.toURI()); } catch (Exception ex) { - log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URI, ex); + log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URL, ex); } } else { - log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URI); + log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URL); } } else { - log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URI); + log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URL); } } log.info("BKU successfully started"); @@ -276,6 +303,39 @@ public class Launcher implements BKUControllerInterface { System.exit(0); } + /** + * Listen for TrayMenu actions (display error messages on trayIcon) + * @param e + */ + @Override + public void actionPerformed(ActionEvent e) { + if (SHUTDOWN_COMMAND.equals(e.getActionCommand())) { + log.debug("shutdown requested via tray menu"); + this.shutDown(); + } else if (ABOUT_COMMAND.equals(e.getActionCommand())) { + log.debug("about dialog requested via tray menu"); + if (aboutDialog == null) { + aboutDialog = new AboutDialog(new JFrame(), true, version); + aboutDialog.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(java.awt.event.WindowEvent e) { + aboutDialog.setVisible(false); + } + }); + } + aboutDialog.setLocationByPlatform(true); + aboutDialog.setVisible(true); + } else if (PIN_COMMAND.equals(e.getActionCommand())) { + log.debug("pin management dialog requested via tray menu"); + + new Thread(new PINManagementInvoker(trayIcon, messages)).start(); + + } else { + log.error("unknown tray menu command: " + e.getActionCommand()); + } + } + public static void main(String[] args) throws InterruptedException, IOException { try { Launcher launcher = new Launcher(); diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java new file mode 100644 index 00000000..55e26313 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java @@ -0,0 +1,71 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.webstart.gui; + +import at.gv.egiz.bku.webstart.Launcher; +import java.awt.TrayIcon; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.ResourceBundle; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * GUI is painted using SwingUtilities.invokeLater, but TrayIcon ActionListener Thread (== webstart thread) joined Jetty Thread + * + * @author Clemens Orthacker + */ +public class PINManagementInvoker implements Runnable { + + private static final Log log = LogFactory.getLog(PINManagementInvoker.class); + + TrayIcon trayIcon; + ResourceBundle messages; + + public PINManagementInvoker(TrayIcon trayIcon, ResourceBundle messages) { + this.trayIcon = trayIcon; + this.messages = messages; + } + + @Override + public void run() { + HttpURLConnection connection = null; + try { + log.debug("Connecting to: " + Launcher.PIN_MANAGEMENT_URL); + + connection = (HttpURLConnection) Launcher.PIN_MANAGEMENT_URL.openConnection(); + + connection.setRequestMethod("GET"); + connection.setReadTimeout(0); + connection.connect(); + + if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { + log.debug("pin management dialog returned"); + } else { + log.error("unexpected response from pin management: " + connection.getResponseMessage()); + } + } catch (IOException ex) { + log.error("Failed to connect to PIN Management", ex); + trayIcon.displayMessage(messages.getString(Launcher.CAPTION_ERROR), + messages.getString(Launcher.ERROR_PIN), TrayIcon.MessageType.ERROR); + } finally { + if (connection != null) { + connection.disconnect(); + } + } + } +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/TrayMenuListener.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/TrayMenuListener.java deleted file mode 100644 index 1e5efe8e..00000000 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/TrayMenuListener.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * 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 at.gv.egiz.bku.webstart.gui; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.util.ResourceBundle; -import javax.swing.JFrame; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author Clemens Orthacker - */ -public class TrayMenuListener implements ActionListener { - - /** action commands for tray menu */ - public static final String SHUTDOWN_COMMAND = "shutdown"; - public static final String PIN_COMMAND = "pin"; - public static final String ABOUT_COMMAND = "about"; - - private static final Log log = LogFactory.getLog(TrayMenuListener.class); - - protected BKUControllerInterface bku; - protected ResourceBundle messages; - protected String version; - protected AboutDialog aboutDialog; - - public TrayMenuListener(BKUControllerInterface bkuHook, ResourceBundle messages, String version) { - this.messages = messages; - this.version = version; - this.bku = bkuHook; - } - - @Override - public void actionPerformed(ActionEvent e) { - if (SHUTDOWN_COMMAND.equals(e.getActionCommand())) { - log.debug("shutdown requested via tray menu"); - bku.shutDown(); - } else if (ABOUT_COMMAND.equals(e.getActionCommand())) { - log.debug("about dialog requested via tray menu"); - if (aboutDialog == null) { - aboutDialog = new AboutDialog(new JFrame(), true, version); - aboutDialog.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(java.awt.event.WindowEvent e) { - aboutDialog.setVisible(false); - } - }); - } - aboutDialog.setLocationByPlatform(true); - aboutDialog.setVisible(true); - } else if (PIN_COMMAND.equals(e.getActionCommand())) { - log.error("not implemented yet."); - } else { - log.error("unknown tray menu command: " + e.getActionCommand()); - } - } -} diff --git a/BKUWebStart/src/main/jnlp/resources/version.xml b/BKUWebStart/src/main/jnlp/resources/version.xml index 013194a4..64a3963e 100644 --- a/BKUWebStart/src/main/jnlp/resources/version.xml +++ b/BKUWebStart/src/main/jnlp/resources/version.xml @@ -2,17 +2,17 @@ - BKUWebStart-1.0.10.jar - 1.0.10 + BKUWebStart-1.0.11-SNAPSHOT.jar + 1.0.11-SNAPSHOT - BKUWebStart-1.0.10.jar + BKUWebStart-1.0.11-SNAPSHOT.jar - utils-1.2.1.jar - 1.2.1 + utils-1.2.2-SNAPSHOT.jar + 1.2.2-SNAPSHOT - utils-1.2.1.jar + utils-1.2.2-SNAPSHOT.jar diff --git a/BKUWebStart/src/main/resources/at/gv/egiz/bku/webstart/messages.properties b/BKUWebStart/src/main/resources/at/gv/egiz/bku/webstart/messages.properties index d965f970..b6d9238e 100644 --- a/BKUWebStart/src/main/resources/at/gv/egiz/bku/webstart/messages.properties +++ b/BKUWebStart/src/main/resources/at/gv/egiz/bku/webstart/messages.properties @@ -24,6 +24,7 @@ tray.message.shutdown=B\u00FCrgerkartenumgebung wird beendet tray.error.start=B\u00FCrgerkartenumgebung konnte nicht gestartet werden tray.error.config=Konfiguration konnte nicht initialisiert werden, B\u00FCrberkartenumgebung wird nicht gestartet tray.error.bind=Die f\u00FCr die B\u00FCrgerkartenumgebung reservierte Adresse wird bereits von einem anderen Dienst verwendet +tray.error.pin.connect=Verbindung zur PIN Verwaltung konnte nicht hergestellt werden tray.label.shutdown=Beenden tray.label.pin=PIN Verwaltung tray.label.about=\u00DCber... diff --git a/pom.xml b/pom.xml index 912d29d0..7f98c2ec 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,8 @@ BKUWebStart BKUCertificates BKUHelp + BKUGuiExt + smccSTALExt diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java index 71f35181..d0762da9 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -160,6 +160,11 @@ public abstract class AbstractSMCCSTAL implements STAL { handlerMap.put(id.getSimpleName(), handler); } + public void removeRequestHandler(Class id) { + log.debug("De-registering STAL request handler: " + id.getSimpleName()); + handlerMap.remove(id.getSimpleName()); + } + public SMCCSTALRequestHandler getRequestHandler( Class request) { return handlerMap.get(request.getSimpleName()); diff --git a/smccSTALExt/pom.xml b/smccSTALExt/pom.xml new file mode 100644 index 00000000..481993e1 --- /dev/null +++ b/smccSTALExt/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + bku + at.gv.egiz + 1.2.2-SNAPSHOT + + at.gv.egiz + smccSTALExt + ${project.parent.version} + smcc STAL Extension + + + at.gv.egiz + smccSTAL + ${project.parent.version} + + + at.gv.egiz + BKUGuiExt + ${project.parent.version} + + + + diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/CardMgmtRequestHandler.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/CardMgmtRequestHandler.java new file mode 100644 index 00000000..533206b3 --- /dev/null +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/CardMgmtRequestHandler.java @@ -0,0 +1,177 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.bku.smccstal; + +import at.gv.egiz.bku.gui.ActivationGUIFacade; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.smartcardio.Card; +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.smccstal.AbstractRequestHandler; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.ext.APDUScriptRequest; +import at.gv.egiz.stal.ext.APDUScriptResponse; +import at.gv.egiz.stal.ext.APDUScriptRequest.Command; +import at.gv.egiz.stal.ext.APDUScriptRequest.RequestScriptElement; +import at.gv.egiz.stal.ext.APDUScriptRequest.Reset; +import at.gv.egiz.stal.ext.APDUScriptResponse.Response; +import at.gv.egiz.stal.ext.APDUScriptResponse.ATR; +import at.gv.egiz.stal.ext.APDUScriptResponse.ResponseScriptElement; +import java.awt.event.ActionListener; + +/** + * @author mcentner + * + */ +public class CardMgmtRequestHandler extends AbstractRequestHandler implements ActionListener { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(CardMgmtRequestHandler.class); + + /** + * The sequence counter. + */ + private int sequenceNum = 0; + + /** + * display script num + */ + private int currentActivationScript = 0; + + @Override + public STALResponse handleRequest(STALRequest request) + throws InterruptedException { + + // APDU Script Request + if (request instanceof APDUScriptRequest) { + + currentActivationScript++; + log.debug("handling APDU script " + currentActivationScript); + + Card icc = card.getCard(); + + if (icc == null) { + log.error("SignatureCard instance '" + card.getClass().getName() + "' does not support card management requests."); + return new ErrorResponse(1000); + } + + List script = ((APDUScriptRequest) request).getScript(); + ArrayList responses = new ArrayList(script.size()); + + ((ActivationGUIFacade) gui).showActivationProgressDialog(currentActivationScript, script.size(), this, "cancel"); + + try { + log.trace("begin exclusive"); + icc.beginExclusive(); + + for (RequestScriptElement scriptElement : script) { + ((ActivationGUIFacade) gui).incrementProgress(); + + if (scriptElement instanceof Command) { + log.trace("handling APDU script element COMMAND"); + Command command = (Command) scriptElement; + CommandAPDU commandAPDU = new CommandAPDU(command.getCommandAPDU()); + + log.trace("get basicchannel"); + CardChannel channel = icc.getBasicChannel(); + + sequenceNum = command.getSequence(); + log.debug("Transmit APDU (sequence=" + sequenceNum + ")"); + log.trace(commandAPDU.toString()); + ResponseAPDU responseAPDU = channel.transmit(commandAPDU); + log.trace(responseAPDU.toString()); + + byte[] sw = new byte[] { + (byte) (0xFF & responseAPDU.getSW1()), + (byte) (0xFF & responseAPDU.getSW2()) }; + + responses.add(new Response(sequenceNum, responseAPDU.getData(), sw, 0)); + + if (command.getExpectedSW() != null && + !Arrays.equals(sw, command.getExpectedSW())) { + // unexpected SW + log.warn("Got unexpected SW. APDU-script execution stopped."); + break; + } + + } else if (scriptElement instanceof Reset) { + + log.trace("handling APDU script element RESET"); + sequenceNum = 0; + card.reset(); + javax.smartcardio.ATR atr = icc.getATR(); + log.trace("got ATR: " + atr.toString()); + responses.add(new ATR(atr.getBytes())); + + log.trace("regain exclusive access to card"); + icc = card.getCard(); + icc.beginExclusive(); + } + + } + + } catch (CardException e) { + log.info("Failed to execute APDU script.", e); + responses.add(new Response(sequenceNum, null, null, Response.RC_UNSPECIFIED)); + } catch (SignatureCardException e) { + log.info("Failed to reset smart card.", e); + responses.add(new Response(sequenceNum, null, null, Response.RC_UNSPECIFIED)); + } catch (RuntimeException e) { + log.error(e); + throw e; + } finally { + try { + icc.endExclusive(); + } catch (CardException e) { + log.info(e); + } + } + + log.trace("done handling APDU script " + currentActivationScript + ", return response containing " + responses.size() + " elements"); + ((ActivationGUIFacade) gui).showIdleDialog(this, "cancel"); + return new APDUScriptResponse(responses); + + } else { + log.error("Got unexpected STAL request: " + request); + return new ErrorResponse(1000); + } + + } + + @Override + public boolean requireCard() { + return true; + } + +} diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/GetPINStatusException.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/GetPINStatusException.java new file mode 100644 index 00000000..66b15887 --- /dev/null +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/GetPINStatusException.java @@ -0,0 +1,41 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; + +import at.gv.egiz.smcc.SignatureCardException; + +/** + * + * @author Clemens Orthacker + */ +public class GetPINStatusException extends SignatureCardException { + + /** + * Creates a new instance of GetStatusException without detail message. + */ + public GetPINStatusException() { + } + + + /** + * Constructs an instance of GetStatusException with the specified detail message. + * @param msg the detail message. + */ + public GetPINStatusException(String msg) { + super(msg); + } +} diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java new file mode 100644 index 00000000..34bcbf5c --- /dev/null +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java @@ -0,0 +1,262 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.ChangePINProvider; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.smccstal.AbstractPINProvider; +import at.gv.egiz.bku.smccstal.PINProviderFactory; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.ccid.CCID; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCard; + +/** + * + * @author Clemens Orthacker + */ +public class ManagementPINProviderFactory extends PINProviderFactory { + + public ManagementPINProviderFactory(CCID reader, PINManagementGUIFacade gui) { + super(reader, gui); + } + +// public static ManagementPINProviderFactory getInstance(SignatureCard forCard, +// PINManagementGUIFacade gui) { +// if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { +// return new PinpadPINProviderFactory(gui); +// +// } else { +// return new SoftwarePINProviderFactory(gui); +// } +// } + + public PINProvider getVerifyPINProvider() { + if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); + } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); + } else { + return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); + } + } + + public PINProvider getActivatePINProvider() { + if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); + } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); + } else { + return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); + } + } + + public ChangePINProvider getChangePINProvider() { + if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.CHANGE); + } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.CHANGE); + } else { + return new ChangePinProvider(); + } + } + + public PINProvider getUnblockPINProvider() { + if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); + } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { + return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); + } else { + return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); + } + } + + class PinpadGenericPinProvider extends AbstractPINProvider + implements ChangePINProvider { + + protected PINManagementGUIFacade.DIALOG type; + + private PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG type) { + this.type = type; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + showPinpadPINDialog(retries, spec); + retry = true; + return null; + } + + /** + * do not call this method without calling providePIN() + * (no message is displayed) + * @param spec + * @param retries + * @return + */ + @Override + public char[] provideOldPIN(PINSpec spec, int retries) { + return null; + } + + private void showPinpadPINDialog(int retries, PINSpec pinSpec) { + String title, message; + Object[] params; + if (retry) { + if (retries == 1) { + message = BKUGUIFacade.MESSAGE_LAST_RETRY_PINPAD; + } else { + message = BKUGUIFacade.MESSAGE_RETRIES_PINPAD; + } + title = BKUGUIFacade.TITLE_RETRY; + params = new Object[]{String.valueOf(retries)}; + } else if (type == PINManagementGUIFacade.DIALOG.VERIFY) { + title = PINManagementGUIFacade.TITLE_VERIFY_PIN; + message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { + title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; + message = PINManagementGUIFacade.MESSAGE_ACTIVATEPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { + title = PINManagementGUIFacade.TITLE_CHANGE_PIN; + message = PINManagementGUIFacade.MESSAGE_CHANGEPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else { //if (type == DIALOG.UNBLOCK) { + title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; + message = PINManagementGUIFacade.MESSAGE_UNBLOCKPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } + gui.showMessageDialog(title, message, params); + } + } + + + class SoftwareGenericPinProvider extends AbstractPINProvider { + +// protected PINManagementGUIFacade gui; + protected PINManagementGUIFacade.DIALOG type; + + private SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG type) { + this.type = type; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + ((PINManagementGUIFacade) gui).showPINDialog(type, spec, + (retry) ? retries : -1, + this, "exec", + this, "back"); + + waitForAction(); + + if ("exec".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + retry = true; + return gui.getPin(); + } else if ("back".equals(action)) { + throw new CancelledException(); + } else { + log.error("unsupported command " + action); + throw new CancelledException(); + } + } + } + + class ChangePinProvider extends AbstractPINProvider + implements ChangePINProvider { + +// protected PINManagementGUIFacade gui; + + private char[] oldPin; + private char[] newPin; + + private ChangePinProvider() { + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (newPin == null) { + getPINs(spec, retries); + } + char[] pin = newPin; + newPin = null; + return pin; + } + + @Override + public char[] provideOldPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (oldPin == null) { + getPINs(spec, retries); + } + char[] pin = oldPin; + oldPin = null; + return pin; + } + + private void getPINs(PINSpec spec, int retries) + throws InterruptedException, CancelledException { + + ((PINManagementGUIFacade) gui).showPINDialog( + PINManagementGUIFacade.DIALOG.CHANGE, spec, + (retry) ? retries : -1, + this, "exec", + this, "back"); + + waitForAction(); + + if ("exec".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + retry = true; + oldPin = ((PINManagementGUIFacade) gui).getOldPin(); + newPin = gui.getPin(); + } else if ("back".equals(action)) { + throw new CancelledException(); + } else { + log.error("unsupported command " + action); + throw new CancelledException(); + } + } + } +} diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java new file mode 100644 index 00000000..bfeb90b0 --- /dev/null +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java @@ -0,0 +1,245 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.smccstal; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; +import at.gv.egiz.bku.smccstal.AbstractRequestHandler; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.LockedException; +import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.PINConfirmationException; +import at.gv.egiz.smcc.PINFormatException; +import at.gv.egiz.smcc.PINMgmtSignatureCard; +import at.gv.egiz.smcc.PINOperationAbortedException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.TimeoutException; +import at.gv.egiz.smcc.PINMgmtSignatureCard.PIN_STATE; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.ext.PINManagementRequest; +import at.gv.egiz.stal.ext.PINManagementResponse; + +/** + * + * @author Clemens Orthacker + */ +public class PINManagementRequestHandler extends AbstractRequestHandler { + + protected static final Log log = LogFactory.getLog(PINManagementRequestHandler.class); + + protected Map pinStates = new HashMap(); + + @Override + public STALResponse handleRequest(STALRequest request) throws InterruptedException { + if (request instanceof PINManagementRequest) { + + PINManagementGUIFacade gui = (PINManagementGUIFacade) this.gui; + + PINSpec selectedPIN = null; + + try { + + if (card instanceof PINMgmtSignatureCard) { + + // update all PIN states + for (PINSpec pinSpec : ((PINMgmtSignatureCard) card).getPINSpecs()) { + updatePINState(pinSpec, STATUS.UNKNOWN); + } + + gui.showPINManagementDialog(pinStates, this, "activate_enterpin", + "change_enterpin", "unblock_enterpuk", "verify_enterpin", this, + "cancel"); + + } else { + + // card does not support PIN management + gui.showErrorDialog(PINManagementGUIFacade.ERR_UNSUPPORTED_CARD, + null, this, "cancel"); + + } + + while (true) { + + waitForAction(); + + if ("cancel".equals(actionCommand)) { + log.debug("pin management cancel"); + return new PINManagementResponse(); + } else { + selectedPIN = gui.getSelectedPINSpec(); + + if (selectedPIN == null) { + throw new NullPointerException("no PIN selected for activation/change"); + } + + ManagementPINProviderFactory ppfac = + new ManagementPINProviderFactory(card.getReader(), gui); + + try { + if ("activate_enterpin".equals(actionCommand)) { + log.info("activate " + selectedPIN.getLocalizedName()); + ((PINMgmtSignatureCard) card).activatePIN(selectedPIN, + ppfac.getActivatePINProvider()); + updatePINState(selectedPIN, STATUS.ACTIV); + gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, + PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, + new Object[] {selectedPIN.getLocalizedName()}, + BKUGUIFacade.BUTTON_OK, this, "ok"); + waitForAction(); + } else if ("change_enterpin".equals(actionCommand)) { + log.info("change " + selectedPIN.getLocalizedName()); + ((PINMgmtSignatureCard) card).changePIN(selectedPIN, + ppfac.getChangePINProvider()); + updatePINState(selectedPIN, STATUS.ACTIV); + gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, + PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, + new Object[] {selectedPIN.getLocalizedName()}, + BKUGUIFacade.BUTTON_OK, this, "ok"); + waitForAction(); + + } else if ("unblock_enterpuk".equals(actionCommand)) { + log.info("unblock " + selectedPIN.getLocalizedName()); + ((PINMgmtSignatureCard) card).unblockPIN(selectedPIN, + ppfac.getUnblockPINProvider()); + } else if ("verify_enterpin".equals(actionCommand)) { + log.info("verify " + selectedPIN.getLocalizedName()); + ((PINMgmtSignatureCard) card).verifyPIN(selectedPIN, + ppfac.getVerifyPINProvider()); + updatePINState(selectedPIN, STATUS.ACTIV); + } + } catch (CancelledException ex) { + log.trace("cancelled"); + } catch (TimeoutException ex) { + log.error("Timeout during pin entry"); + gui.showMessageDialog(BKUGUIFacade.TITLE_ENTRY_TIMEOUT, + BKUGUIFacade.ERR_PIN_TIMEOUT, + new Object[] {selectedPIN.getLocalizedName()}, + BKUGUIFacade.BUTTON_OK, this, null); + waitForAction(); + } catch (LockedException ex) { + log.error(selectedPIN.getLocalizedName() + " locked"); + updatePINState(selectedPIN, STATUS.BLOCKED); + gui.showErrorDialog(PINManagementGUIFacade.ERR_LOCKED, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (NotActivatedException ex) { + log.error(selectedPIN.getLocalizedName() + " not active"); + updatePINState(selectedPIN, STATUS.NOT_ACTIV); + gui.showErrorDialog(PINManagementGUIFacade.ERR_NOT_ACTIVE, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (PINConfirmationException ex) { + log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (PINOperationAbortedException ex) { + log.error("pin operation aborted without further details"); + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_OPERATION_ABORTED, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (PINFormatException ex) { + log.error("wrong format of new " + selectedPIN.getLocalizedName()); +// updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); + String pinSize = String.valueOf(selectedPIN.getMinLength()); + if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { + pinSize += "-" + selectedPIN.getMaxLength(); + } + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, + new Object[] {selectedPIN.getLocalizedName(), pinSize}, + this, null); + waitForAction(); + } + } // end if + + selectedPIN = null; + gui.showPINManagementDialog(pinStates, + this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", "verify_enterpin", + this, "cancel"); + } // end while + + } catch (GetPINStatusException ex) { + String pin = (selectedPIN != null) ? selectedPIN.getLocalizedName() : "pin"; + log.error("failed to get " + pin + " status: " + ex.getMessage()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_STATUS, null, + this, "ok"); + waitForAction(); + return new ErrorResponse(1000); + } catch (SignatureCardException ex) { + log.error(ex.getMessage(), ex); + gui.showErrorDialog(PINManagementGUIFacade.ERR_UNKNOWN, null, + this, "ok"); + waitForAction(); + return new ErrorResponse(1000); + } + } else { + log.error("Got unexpected STAL request: " + request); + return new ErrorResponse(1000); + } + } + + @Override + public boolean requireCard() { + return true; + } + + /** + * query status for STARCOS card, + * assume provided status for ACOS card + * @param pinSpec + * @param status + * @throws at.gv.egiz.smcc.SignatureCardException if query status fails + */ + private void updatePINState(PINSpec pinSpec, STATUS status) + throws GetPINStatusException { + + PINMgmtSignatureCard pmCard = ((PINMgmtSignatureCard) card); + PIN_STATE pinState; + try { + pinState = pmCard.getPINState(pinSpec); + } catch (SignatureCardException e) { + String msg = "Failed to get PIN status for pin '" + + pinSpec.getLocalizedName() + "'."; + log.info(msg, e); + throw new GetPINStatusException(msg); + } + if (pinState == PIN_STATE.ACTIV) { + pinStates.put(pinSpec, STATUS.ACTIV); + } else if (pinState == PIN_STATE.NOT_ACTIV) { + pinStates.put(pinSpec, STATUS.NOT_ACTIV); + } else if (pinState == PIN_STATE.BLOCKED) { + pinStates.put(pinSpec, STATUS.BLOCKED); + } else { + pinStates.put(pinSpec, status); + } + } + +} -- cgit v1.2.3 From caca721368d8c24559b1cd5ea2018884b4874f6b Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 10 Nov 2009 15:30:16 +0000 Subject: Removed switchFocusListener due to problem with viewer/help dialogs on Firefox/Mac git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@539 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/bku/online/applet/BKUApplet.java | 5 +---- .../bku/online/applet/viewer/URLFontLoader.java | 8 +++---- .../main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java | 18 +++++++-------- .../at/gv/egiz/bku/gui/SecureViewerDialog.java | 15 ++++++------- .../at/gv/egiz/bku/gui/SwitchFocusListener.java | 4 ++-- BKUOnline/src/main/webapp/applet.jsp | 26 +--------------------- .../gv/egiz/bku/smccstal/AbstractPINProvider.java | 4 ++-- .../gv/egiz/bku/smccstal/PINProviderFactory.java | 5 +++++ 8 files changed, 31 insertions(+), 54 deletions(-) (limited to 'smccSTAL/src') diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java index 2094e55c..895fdbb5 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java @@ -187,9 +187,6 @@ public class BKUApplet extends JApplet { log.warn("failed to load help URL: " + ex.getMessage() + ", disabling help"); } - SwitchFocusListener switchFocusListener = new SwitchFocusListener( - getAppletContext(), "focusToBrowser()"); - // Note: We need a panel in order to be able to set the background // properly. // Setting the background without a panel has side effects with the @@ -212,7 +209,7 @@ public class BKUApplet extends JApplet { URLFontLoader fontProvider = new URLFontLoader(getCodeBase()); fontProvider.loadInBackground(); BKUGUIFacade gui = createGUI(contentPanel, getLocale(), guiStyle, - backgroundImgURL, fontProvider, helpListener, switchFocusListener); + backgroundImgURL, fontProvider, helpListener, null); worker = createBKUWorker(this, gui); } catch (MalformedURLException ex) { diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/viewer/URLFontLoader.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/viewer/URLFontLoader.java index f914aed7..49615887 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/viewer/URLFontLoader.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/viewer/URLFontLoader.java @@ -41,13 +41,13 @@ public class URLFontLoader extends SwingWorker implements FontProv public URLFontLoader(URL codebase) throws MalformedURLException { this.fontURL = new URL(codebase, SANSMONO_FONT_RESOURCE); if (log.isDebugEnabled()) { - log.debug(Thread.currentThread() + " setting font load URL: " + fontURL); + log.debug("[" + Thread.currentThread().getName() + "] setting font load URL: " + fontURL); } } public void loadInBackground() { if (log.isDebugEnabled()) { - log.debug(Thread.currentThread() + " scheduling font loading in background: " + fontURL); + log.debug("[" + Thread.currentThread().getName() + "] scheduling font loading in background: " + fontURL); } this.execute(); } @@ -55,7 +55,7 @@ public class URLFontLoader extends SwingWorker implements FontProv @Override protected Font doInBackground() throws MalformedURLException, FontFormatException, IOException { if (log.isDebugEnabled()) { - log.debug(Thread.currentThread() + " loading font in background..."); + log.debug("[" + Thread.currentThread().getName() + "] loading font in background..."); } return Font.createFont(Font.TRUETYPE_FONT, fontURL.openStream()); } @@ -67,7 +67,7 @@ public class URLFontLoader extends SwingWorker implements FontProv */ @Override public Font getFont() throws FontProviderException { - log.debug(Thread.currentThread() + " get font"); + log.debug("[" + Thread.currentThread().getName() + "] get font (EDT?)"); try { return get(); } catch (InterruptedException ex) { diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java index 8df4bd72..34f278fb 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -159,7 +159,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("initializing gui [" + Thread.currentThread().getName() + "]"); + log.debug("[" + Thread.currentThread().getName() + "] initializing gui"); if (renderIconPanel) { initIconPanel(background); @@ -565,7 +565,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show card-pin dialog [" + Thread.currentThread().getName() + "]"); + log.debug("[" + Thread.currentThread().getName() + "] show card-pin dialog"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -758,7 +758,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show pinpad signature-pin dialog [" + Thread.currentThread().getName() + "]"); + log.debug("[" + Thread.currentThread().getName() + "] show pinpad signature-pin dialog"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -927,7 +927,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show signature-pin dialog [" + Thread.currentThread().getName() + "]"); + log.debug("[" + Thread.currentThread().getName() + "] show signature-pin dialog"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -1215,7 +1215,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show message dialog [" + Thread.currentThread().getName() + "]"); + log.debug("[" + Thread.currentThread().getName() + "] show message dialog"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -1385,7 +1385,7 @@ public class BKUGUIImpl implements BKUGUIFacade { backListener, backCommand); } else if (dataToBeSigned.size() == 1) { try { - log.debug("scheduling secure viewer"); + log.debug("[" + Thread.currentThread().getName() + "] scheduling secure viewer"); SwingUtilities.invokeLater(new Runnable() { @@ -1419,7 +1419,7 @@ public class BKUGUIImpl implements BKUGUIFacade { */ private void showSecureViewer(HashDataInput dataToBeSigned) throws FontProviderException { - log.debug("show secure viewer [" + Thread.currentThread().getName() + "]"); + log.debug("[" + Thread.currentThread().getName() + "] show secure viewer"); if (secureViewer == null) { secureViewer = new SecureViewerDialog(null, messages, fontProvider, helpMouseListener.getActionListener()); @@ -1439,14 +1439,14 @@ public class BKUGUIImpl implements BKUGUIFacade { private void showSignedReferencesListDialog(final List signedReferences, final ActionListener backListener, final String backCommand) { - log.debug("scheduling signed references list dialog"); + log.debug("[" + Thread.currentThread().getName() + "] scheduling signed references list dialog"); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - log.debug("show signed references list dialog [" + Thread.currentThread().getName() + "]"); + log.debug("[" + Thread.currentThread().getName() + "] show signed references list dialog"); mainPanel.removeAll(); buttonPanel.removeAll(); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java index c0b14a85..878a998b 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java @@ -54,8 +54,6 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.LayoutStyle; import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.text.DefaultEditorKit; import javax.swing.text.Document; import javax.swing.text.EditorKit; import javax.swing.text.StyledEditorKit; @@ -73,7 +71,6 @@ public class SecureViewerDialog extends JDialog implements ActionListener { * BKUApplet includes BKUFonts as runtime dependency only, the jar is copied to the applet dir in BKUOnline with dependency-plugin * BKUViewer has compile dependency BKUFonts, transitive in BKUOnline and BKULocal */ - public static final String PLAINTEXT_FONT_RESOURCE = "DejaVuSansMono.ttf"; public static final Dimension VIEWER_DIMENSION = new Dimension(600, 400); protected static final Log log = LogFactory.getLog(SecureViewerDialog.class); // private static SecureViewerDialog dialog; @@ -227,6 +224,8 @@ public class SecureViewerDialog extends JDialog implements ActionListener { */ public void setContent(HashDataInput hashDataInput) { //throws FontProviderException { + log.debug("[" + Thread.currentThread().getName() + "] set viewer content"); + this.content = null; viewer.setText(null); @@ -285,6 +284,7 @@ public class SecureViewerDialog extends JDialog implements ActionListener { viewerLabel.setText(""); } + log.debug("VIEWER FONT: " + viewer.getFont()); setVisible(true); toFront(); } @@ -320,12 +320,11 @@ public class SecureViewerDialog extends JDialog implements ActionListener { @Override public void actionPerformed(ActionEvent e) { if ("close".equals(e.getActionCommand())) { -// SecureViewerDialog.dialog.setVisible(false); - log.trace(Thread.currentThread() + " closing secure viewer"); + log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer"); setVisible(false); log.trace("secure viewer closed"); } else if ("save".equals(e.getActionCommand())) { - log.trace(Thread.currentThread() + " display secure viewer save dialog"); + log.trace("[" + Thread.currentThread().getName() + "] display secure viewer save dialog"); showSaveDialog(content, null, null); log.trace("done secure viewer save"); } else { @@ -336,14 +335,14 @@ public class SecureViewerDialog extends JDialog implements ActionListener { private void showSaveDialog(final HashDataInput hashDataInput, final ActionListener okListener, final String okCommand) { - log.debug("scheduling save dialog [" + Thread.currentThread().getName() + "]"); + log.debug("[" + Thread.currentThread().getName() + "] scheduling save dialog"); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - log.debug("show save dialog [" + Thread.currentThread().getName() + "]"); + log.debug("[" + Thread.currentThread().getName() + "] show save dialog"); String userHome = System.getProperty("user.home"); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java index 1e3fabbd..48b641e2 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java @@ -33,8 +33,8 @@ public class SwitchFocusListener implements ActionListener { ctx.showDocument (new URL("javascript:" + javascriptFunction)); } - catch (MalformedURLException me) { - + catch (MalformedURLException me) { + log.warn("Unable to call external javascript function.", me); } diff --git a/BKUOnline/src/main/webapp/applet.jsp b/BKUOnline/src/main/webapp/applet.jsp index df0b3ca5..423b349e 100644 --- a/BKUOnline/src/main/webapp/applet.jsp +++ b/BKUOnline/src/main/webapp/applet.jsp @@ -71,7 +71,7 @@ } %> - + - - diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java index e2499023..bc52c955 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java @@ -47,7 +47,7 @@ public abstract class AbstractPINProvider implements PINProvider, ActionListener this.wait(); } } catch (InterruptedException e) { - log.error("interrupt in waitForAction"); + log.error("[" + Thread.currentThread().getName() + "] interrupt in waitForAction"); throw e; } actionPerformed = false; @@ -60,7 +60,7 @@ public abstract class AbstractPINProvider implements PINProvider, ActionListener @Override public void actionPerformed(ActionEvent e) { - log.debug("command " + e.getActionCommand()); + log.debug("[" + Thread.currentThread().getName() + "] action performed - " + e.getActionCommand()); action = e.getActionCommand(); actionPerformed(); } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java index 543fbb3a..e5afe0ae 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java @@ -116,7 +116,9 @@ public class PINProviderFactory { this, "secureViewer"); do { + log.debug("[" + Thread.currentThread().getName() + "] wait for action"); waitForAction(); + log.debug("[" + Thread.currentThread().getName() + "] received action"); if ("secureViewer".equals(action)) { try { @@ -169,6 +171,7 @@ public class PINProviderFactory { this, "ok", this, "cancel"); + log.debug("[" + Thread.currentThread().getName() + "] wait for action"); waitForAction(); gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, @@ -216,7 +219,9 @@ public class PINProviderFactory { PinpadSignaturePinProvider.this, "secureViewer"); while (true) { + log.debug("[" + Thread.currentThread().getName() + "] wait for action"); waitForAction(); + log.debug("[" + Thread.currentThread().getName() + "] received action"); if ("secureViewer".equals(action)) { viewer.displayDataToBeSigned(signedInfo, -- cgit v1.2.3 From 68941b57df2caeead67a5bede2ef5a635d07db32 Mon Sep 17 00:00:00 2001 From: mcentner Date: Wed, 11 Nov 2009 15:51:08 +0000 Subject: Added support for SHA-256 and partial support for e-card G3, BELPIC and Italian cards. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@540 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/stal/util/JCEAlgorithmNames.java | 51 ---- .../java/at/gv/egiz/bku/conf/Configurator.java | 71 +++-- .../at/gv/egiz/bku/slcommands/impl/STALHelper.java | 26 +- .../impl/xsect/AlgorithmMethodFactoryImpl.java | 86 ++++-- .../bku/slcommands/impl/xsect/STALProvider.java | 6 +- .../egiz/bku/slcommands/impl/xsect/Signature.java | 23 +- .../slexceptions/SLExceptionMessages.properties | 2 +- .../slexceptions/SLExceptionMessages_en.properties | 2 +- smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 55 +++- smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java | 283 ++++++++++++++++++++ smcc/src/main/java/at/gv/egiz/smcc/ITCard.java | 297 +++++++++++++++++++++ .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 192 +++++++++---- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 8 +- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 11 +- .../java/at/gv/egiz/smcc/SignatureCardFactory.java | 96 +++++-- .../java/at/gv/egiz/smcc/util/ISO7816Utils.java | 11 +- .../at/gv/egiz/smcc/BELPICCard.properties | 3 + .../resources/at/gv/egiz/smcc/ITCard.properties | 3 + smcc/src/test/java/at/gv/egiz/smcc/CardTest.java | 62 ++--- .../java/at/gv/egiz/smcc/acos/ACOSCardTest.java | 62 ++--- .../at/gv/egiz/smcc/starcos/STARCOSCardTest.java | 62 ++--- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 21 +- .../java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java | 5 +- .../gv/egiz/xades/QualifyingPropertiesFactory.java | 15 +- 24 files changed, 1145 insertions(+), 308 deletions(-) delete mode 100644 STAL/src/main/java/at/gv/egiz/stal/util/JCEAlgorithmNames.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ITCard.java create mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties create mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties (limited to 'smccSTAL/src') diff --git a/STAL/src/main/java/at/gv/egiz/stal/util/JCEAlgorithmNames.java b/STAL/src/main/java/at/gv/egiz/stal/util/JCEAlgorithmNames.java deleted file mode 100644 index c162eed4..00000000 --- a/STAL/src/main/java/at/gv/egiz/stal/util/JCEAlgorithmNames.java +++ /dev/null @@ -1,51 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.stal.util; - -import java.util.HashMap; -import java.util.Map; - -/** - * Maps XML Algorithms to JCE Hash names. - * - */ -public class JCEAlgorithmNames { - - private Map hashNameMap = new HashMap(); - - public static String[] JCE_HASH_NAMES = { "SHA-1" }; - - public static String[] SHA_1_ALGORITMS = { - "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", - "http://www.w3.org/2000/09/xmldsig#rsa-sha1" }; - - private static JCEAlgorithmNames instance = new JCEAlgorithmNames(); - - private JCEAlgorithmNames() { - for (String alg : SHA_1_ALGORITMS) { - registerHash(alg, JCE_HASH_NAMES[0]); - } - } - - public static String getJCEHashName(String xmlAlgorithmURI) { - return instance.hashNameMap.get(xmlAlgorithmURI); - } - - public void registerHash(String xmlAlgorithmURI, String jceName) { - hashNameMap.put(xmlAlgorithmURI, jceName); - } -} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java index 41c2512f..50f5d2b4 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java @@ -166,31 +166,62 @@ public abstract class Configurator { protected void configureProviders() { log.debug("Registering security providers"); - Security.insertProviderAt(new IAIK(), 1); - Security.insertProviderAt(new ECCProvider(false), 2); + + IAIK iaikProvider = new IAIK(); + if (Security.getProvider(iaikProvider.getName()) == null) { + // register IAIK provider at first position + Security.insertProviderAt(iaikProvider, 1); + } else { + // IAIK provider already registered + log.info("Provider " + iaikProvider.getName() + " already registered."); + } + + ECCProvider eccProvider = new ECCProvider(false); + if (Security.getProvider(eccProvider.getName()) == null) { + // register ECC Provider at second position + Security.insertProviderAt(eccProvider, 2); + } else { + // ECC Provider already registered + log.info("Provider " + eccProvider.getName() + " already registered."); + } // registering STALProvider as delegation provider for XSECT STALProvider stalProvider = new STALProvider(); - Set services = stalProvider.getServices(); - StringBuilder sb = new StringBuilder(); - for (Service service : services) { - String algorithm = service.getType() + "." + service.getAlgorithm(); - XSecProvider.setDelegationProvider(algorithm, stalProvider.getName()); - sb.append("\n" + algorithm); + if (Security.getProvider(stalProvider.getName()) == null) { + // register STAL provider + Set services = stalProvider.getServices(); + StringBuilder sb = new StringBuilder(); + for (Service service : services) { + String algorithm = service.getType() + "." + service.getAlgorithm(); + XSecProvider.setDelegationProvider(algorithm, stalProvider.getName()); + sb.append("\n" + algorithm); + } + log + .debug("Registered STALProvider as XSecProvider delegation provider for the following services : " + + sb.toString()); + + Security.addProvider(stalProvider); + } else { + // STAL Provider already registered + log.info("Provider " + stalProvider.getName() + " already registered."); } - log - .debug("Registered STALProvider as XSecProvider delegation provider for the following services : " - + sb.toString()); - - Security.addProvider(stalProvider); - XSecProvider.addAsProvider(false); - sb = new StringBuilder(); - sb.append("Registered providers: "); - int i = 1; - for (Provider prov : Security.getProviders()) { - sb.append((i++) + ". : " + prov); + + if (Security.getProvider(XSecProvider.NAME) == null) { + // register XML Security provider + XSecProvider.addAsProvider(false); + } else { + log.info("Provider " + XSecProvider.NAME + " already registered."); + } + + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("Registered providers: "); + int i = 1; + for (Provider prov : Security.getProviders()) { + sb.append((i++) + ". : " + prov); + } + log.debug(sb.toString()); } - log.debug(sb.toString()); } protected void configViewer() { diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java index 0c7ce3f5..e903c608 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java @@ -18,8 +18,15 @@ package at.gv.egiz.bku.slcommands.impl; import iaik.asn1.CodingException; import iaik.asn1.DerCoder; +import iaik.utils.Base64OutputStream; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.StringWriter; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -174,7 +181,24 @@ public class STALHelper { try { certificates.add((X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(cert))); } catch (CertificateException e) { - log.info("Failed to decode certificate.", e); + if (log.isDebugEnabled()) { + ByteArrayOutputStream certDump = new ByteArrayOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(certDump); + try { + writer.write("-----BEGIN CERTIFICATE-----\n"); + writer.flush(); + Base64OutputStream b64os = new Base64OutputStream(certDump); + b64os.write(cert); + b64os.flush(); + writer.write("\n-----END CERTIFICATE-----"); + writer.flush(); + } catch (IOException e1) { + log.info("Failed to decode certificate.", e); + } + log.debug("Failed to decode certificate.\n" + certDump.toString(), e); + } else { + log.info("Failed to decode certificate.", e); + } throw new SLCommandException(4000, SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, new Object[] { "Certificates" }); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java index 6b963465..061fe707 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java @@ -16,18 +16,23 @@ */ package at.gv.egiz.bku.slcommands.impl.xsect; -import iaik.xml.crypto.XmldsigMore; - -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.X509Certificate; - -import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.crypto.dsig.DigestMethod; -import javax.xml.crypto.dsig.SignatureMethod; -import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; -import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec; -import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; +import iaik.security.ecc.interfaces.ECDSAParams; +import iaik.xml.crypto.XmldsigMore; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.X509Certificate; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.ECParameterSpec; + +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.SignatureMethod; +import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; +import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec; +import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; /** * An implementation of the AlgorithmMethod factory that uses the signing @@ -40,7 +45,12 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory { /** * The signature algorithm URI. */ - private String signatureAlgorithmURI; + private String signatureAlgorithmURI; + + /** + * the digest algorithm URI. + */ + private String digestAlgorithmURI = DigestMethod.SHA1; /** * The algorithm parameters for the signature algorithm. @@ -51,23 +61,55 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory { * Creates a new AlgrithmMethodFactory with the given * signingCertificate. * - * @param siginingCertificate + * @param signingCertificate * * @throws NoSuchAlgorithmException * if the public key algorithm of the given * signingCertificate is not supported */ - public AlgorithmMethodFactoryImpl(X509Certificate siginingCertificate) + public AlgorithmMethodFactoryImpl(X509Certificate signingCertificate) throws NoSuchAlgorithmException { - - String algorithm = siginingCertificate.getPublicKey().getAlgorithm(); + + PublicKey publicKey = signingCertificate.getPublicKey(); + String algorithm = publicKey.getAlgorithm(); if ("DSA".equals(algorithm)) { signatureAlgorithmURI = SignatureMethod.DSA_SHA1; - } else if ("RSA".equals(algorithm)) { - signatureAlgorithmURI = SignatureMethod.RSA_SHA1; - } else if (("EC".equals(algorithm)) || ("ECDSA".equals(algorithm))) { - signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA1; + } else if ("RSA".equals(algorithm)) { + + int keyLength = 0; + if (publicKey instanceof RSAPublicKey) { + keyLength = ((RSAPublicKey) publicKey).getModulus().bitLength(); + } + + if (keyLength >= 2048) { + signatureAlgorithmURI = XmldsigMore.SIGNATURE_RSA_SHA256; + digestAlgorithmURI = DigestMethod.SHA256; + } else { + signatureAlgorithmURI = SignatureMethod.RSA_SHA1; + } + + } else if (("EC".equals(algorithm)) || ("ECDSA".equals(algorithm))) { + + int fieldSize = 0; + if (publicKey instanceof iaik.security.ecc.ecdsa.ECPublicKey) { + ECDSAParams params = ((iaik.security.ecc.ecdsa.ECPublicKey) publicKey).getParameter(); + fieldSize = params.getG().getCurve().getField().getSize().bitLength(); + } else if (publicKey instanceof ECPublicKey) { + ECParameterSpec params = ((ECPublicKey) publicKey).getParams(); + fieldSize = params.getCurve().getField().getFieldSize(); + } + + if (fieldSize < 256) { + signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA1; + } else if (fieldSize < 512) { + signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA256; + digestAlgorithmURI = DigestMethod.SHA256; + } else { + signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA512; + digestAlgorithmURI = DigestMethod.SHA512; + } + } else { throw new NoSuchAlgorithmException("Public key algorithm '" + algorithm + "' not supported."); @@ -104,7 +146,7 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory { throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { return signatureContext.getSignatureFactory().newDigestMethod( - DigestMethod.SHA1, (DigestMethodParameterSpec) null); + digestAlgorithmURI, (DigestMethodParameterSpec) null); } /* diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALProvider.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALProvider.java index 0ab30530..42c6a4c5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALProvider.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALProvider.java @@ -49,7 +49,11 @@ public class STALProvider extends Provider { map.put("Signature." + SignatureMethod.RSA_SHA1, IMPL_PACKAGE_NAME + ".STALSignature"); map.put("Signature." + XmldsigMore.SIGNATURE_ECDSA_SHA1, - IMPL_PACKAGE_NAME + ".STALSignature"); + IMPL_PACKAGE_NAME + ".STALSignature"); + map.put("Signature." + XmldsigMore.SIGNATURE_RSA_SHA256, + IMPL_PACKAGE_NAME + ".STALSignature"); + map.put("Signature." + XmldsigMore.SIGNATURE_ECDSA_SHA256, + IMPL_PACKAGE_NAME + ".STALSignature"); AccessController.doPrivileged(new PrivilegedAction() { @Override diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java index 26ddb153..3cebb6a3 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java @@ -628,9 +628,20 @@ public class Signature { String target = "#" + signatureId; + DigestMethod dm; + try { + dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get DigestMethod algorithm.", e); + throw new SLCommandException(4006); + } catch (InvalidAlgorithmParameterException e) { + log.error("Failed to get DigestMethod algorithm.", e); + throw new SLCommandException(4006); + } + JAXBElement qualifyingProperties; try { - qualifyingProperties = factory.createQualifyingProperties111(target, date, signingCertificates, idValue, dataObjectFormats); + qualifyingProperties = factory.createQualifyingProperties111(target, date, signingCertificates, idValue, dataObjectFormats, dm); } catch (QualifyingPropertiesException e) { log.error("Failed to create QualifyingProperties.", e); throw new SLCommandException(4000); @@ -665,7 +676,10 @@ public class Signature { String referenceURI = "#xmlns(xades=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('" + objectIdValue + "')/child::xades:QualifyingProperties/child::xades:SignedProperties)"; - DigestMethod dm; + + String referenceIdValue = ctx.getIdValueFactory().createIdValue("Reference"); + String referenceType = QualifyingPropertiesFactory.SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1; + try { dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); } catch (NoSuchAlgorithmException e) { @@ -675,10 +689,7 @@ public class Signature { log.error("Failed to get DigestMethod algorithm.", e); throw new SLCommandException(4006); } - - String referenceIdValue = ctx.getIdValueFactory().createIdValue("Reference"); - String referenceType = QualifyingPropertiesFactory.SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1; - + Reference reference = ctx.getSignatureFactory().newReference(referenceURI, dm, null, referenceType, referenceIdValue); references.add(reference); diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties index db56184e..c5bfce18 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties @@ -91,7 +91,7 @@ ec3002.invalid=XML-Struktur der Befehlsanfrage entspricht nicht dem Schema des S # 4xxx # -ec4000.infobox.invalid=Die Infobox '{0}' enthält ungültige Daten. +ec4000.infobox.invalid=Die Infobox {0} enthält ungültige Daten. ec4000.idlink.transfomation.failed=Die komprimierte Personenbindung konnte mit dem Stylesheet {0} nicht transformiert werden. ec4002.infobox.unknown=Unbekannter Infoboxbezeichner {0}. ec4003.not.resolved=Zu signierendes Datum kann nicht aufgelöst werden (URI={0}). diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties index 6c67ba87..a8bffdc6 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties @@ -91,7 +91,7 @@ ec3002.invalid=XML structure of the command request does not comply with the Sec # 4xxx # -ec4000.infobox.invalid=The infobox '{0}' contains invalid content. +ec4000.infobox.invalid=The infobox {0} contains invalid content. ec4000.idlink.transfomation.failed=Failed to transform CompressedIdentityLink with Stylesheet {0}. ec4002.infobox.unknown=Unknown info box identifier {0}. ec4003.not.resolved=Data to be signed cannot be resolved from URI={0}. diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java index 414d4678..a63d4076 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -16,9 +16,13 @@ */ package at.gv.egiz.smcc; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.List; @@ -375,12 +379,46 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC @Override @Exclusive - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, - PINProvider provider) throws SignatureCardException, InterruptedException { + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { - if (hash.length != 20) { - throw new IllegalArgumentException("Hash value must be of length 20."); + ByteArrayOutputStream dst = new ByteArrayOutputStream(); + // key ID + dst.write(new byte[]{(byte) 0x84, (byte) 0x01, (byte) 0x88}); + // algorithm ID + dst.write(new byte[]{(byte) 0x80, (byte) 0x01}); + + MessageDigest md; + try { + if ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1".equals(alg)) { + dst.write((byte) 0x14); // SHA-1/ECC + md = MessageDigest.getInstance("SHA-1"); + } else if ("http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) { + dst.write((byte) 0x12); // SHA-1 with padding according to PKCS#1 block type 01 + md = MessageDigest.getInstance("SHA-1"); + } else if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName) + && appVersion >= 2 + && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256".equals(alg)) { + dst.write((byte) 0x44); // SHA-256/ECC + md = MessageDigest.getInstance("SHA256"); + } else if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName) + && appVersion >= 2 + && "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256".equals(alg)) { + dst.write((byte) 0x41); // SHA-256 with padding according to PKCS#1 + md = MessageDigest.getInstance("SHA256"); + } else { + throw new SignatureCardException("Card does not support signature algorithm " + alg + "."); + } + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get MessageDigest.", e); + throw new SignatureCardException(e); } + + byte[] digest = new byte[md.getDigestLength()]; + for (int l; (l = input.read(digest)) != -1;) { + md.update(digest, 0, l); + } + digest = md.digest(); try { @@ -393,11 +431,11 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC // SELECT application execSELECT_AID(channel, AID_SIG); // MANAGE SECURITY ENVIRONMENT : SET DST - execMSE(channel, 0x41, 0xb6, DST_SIG); + execMSE(channel, 0x41, 0xb6, dst.toByteArray()); // VERIFY verifyPINLoop(channel, spec, provider); // PERFORM SECURITY OPERATION : HASH - execPSO_HASH(channel, hash); + execPSO_HASH(channel, digest); // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATRE return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel); @@ -413,7 +451,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC while (true) { try { // INTERNAL AUTHENTICATE - return execINTERNAL_AUTHENTICATE(channel, hash); + return execINTERNAL_AUTHENTICATE(channel, digest); } catch (SecurityStatusNotSatisfiedException e) { verifyPINLoop(channel, spec, provider); } @@ -711,6 +749,9 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC ResponseAPDU resp = channel.transmit( new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 256)); + if (resp.getSW() == 0x6982) { + throw new SecurityStatusNotSatisfiedException(); + } if (resp.getSW() != 0x9000) { throw new SignatureCardException( "PSO - COMPUTE DIGITAL SIGNATRE failed: SW=" diff --git a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java new file mode 100644 index 00000000..15b47fb0 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java @@ -0,0 +1,283 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc; + +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.util.ISO7816Utils; +import at.gv.egiz.smcc.util.SMCCHelper; + +public class BELPICCard extends AbstractSignatureCard implements SignatureCard { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(BELPICCard.class); + + public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; + + public static final byte[] DF_BELPIC = new byte[] { (byte) 0xDF, + (byte) 0x00 }; + + public static final byte[] DF_ID = new byte[] { (byte) 0xDF, (byte) 0x01 }; + + public static final byte[] SIGN_CERT = new byte[] { (byte) 0x50, + (byte) 0x39 }; + +// public static final byte MSE_SET_ALGO_REF = (byte) 0x02; + +// public static final byte MSE_SET_PRIV_KEY_REF = (byte) 0x83; + + public static final int SIGNATURE_LENGTH = (int) 0x80; + + public static final byte KID = (byte) 0x01; + + public static final int READ_BUFFER_LENGTH = 256; + + public static final int PINSPEC_SS = 0; + + private static final PINSpec SS_PIN_SPEC = + new PINSpec(4, 12, "[0-9]", + "at/gv/egiz/smcc/BelpicCard", "sig.pin", KID, DF_BELPIC); + + /** + * Creates a new instance. + */ + public BELPICCard() { + super("at/gv/egiz/smcc/BelpicCard"); + pinSpecs.add(SS_PIN_SPEC); + } + + @Override + @Exclusive + public byte[] getCertificate(KeyboxName keyboxName) + throws SignatureCardException { + + if (keyboxName != KeyboxName.SECURE_SIGNATURE_KEYPAIR) { + throw new IllegalArgumentException("Keybox " + keyboxName + + " not supported"); + } + + try { + CardChannel channel = getCardChannel(); + // SELECT MF + execSELECT_FID(channel, MF); + // SELECT application + execSELECT_FID(channel, DF_BELPIC); + // SELECT file + execSELECT_FID(channel, SIGN_CERT); + // READ BINARY + byte[] certificate = ISO7816Utils.readTransparentFileTLV(channel, -1, (byte) 0x30); + if (certificate == null) { + throw new NotActivatedException(); + } + return certificate; + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } catch (CardException e) { + log.info("Failed to get certificate.", e); + throw new SignatureCardException(e); + } + + } + + @Override + @Exclusive + public byte[] getInfobox(String infobox, PINProvider provider, String domainId) + throws SignatureCardException, InterruptedException { + + throw new IllegalArgumentException("Infobox '" + infobox + + "' not supported."); + } + + @Override + @Exclusive + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { + + if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { + throw new SignatureCardException("Card does not support key " + keyboxName + "."); + } + if (!"http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) { + throw new SignatureCardException("Card does not support algorithm " + alg + "."); + } + + byte[] dst = new byte[] { (byte) 0x04, // number of following + // bytes + (byte) 0x80, // tag for algorithm reference + (byte) 0x02, // algorithm reference + (byte) 0x84, // tag for private key reference + (byte) 0x83 // private key reference + }; + + MessageDigest md; + try { + md = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get MessageDigest.", e); + throw new SignatureCardException(e); + } + // calculate message digest + byte[] digest = new byte[md.getDigestLength()]; + for (int l; (l = input.read(digest)) != -1;) { + md.update(digest, 0, l); + } + digest = md.digest(); + + try { + + CardChannel channel = getCardChannel(); + + // SELECT MF + execSELECT_FID(channel, MF); + // VERIFY + execMSE(channel, 0x41, 0xb6, dst); + // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE + verifyPINLoop(channel, SS_PIN_SPEC, provider); + // MANAGE SECURITY ENVIRONMENT : SET DST + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest); + + } catch (CardException e) { + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); + } + + } + + public String toString() { + return "Belpic Card"; + } + + protected void verifyPINLoop(CardChannel channel, PINSpec spec, + PINProvider provider) throws LockedException, NotActivatedException, + SignatureCardException, InterruptedException, CardException { + + int retries = -1; //verifyPIN(channel, spec, null, -1); + do { + retries = verifyPIN(channel, spec, provider, retries); + } while (retries > 0); + } + + protected int verifyPIN(CardChannel channel, PINSpec pinSpec, + PINProvider provider, int retries) throws SignatureCardException, + LockedException, NotActivatedException, InterruptedException, + CardException { + + VerifyAPDUSpec apduSpec = new VerifyAPDUSpec( + new byte[] { + (byte) 0x00, (byte) 0x20, (byte) 0x00, pinSpec.getKID(), (byte) 0x08, + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff }, + 1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); + + ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); + + if (resp.getSW() == 0x9000) { + return -1; + } + if (resp.getSW() >> 4 == 0x63c) { + return 0x0f & resp.getSW(); + } + + switch (resp.getSW()) { + case 0x6983: + // authentication method blocked + throw new LockedException(); + case 0x6984: + // reference data not usable + throw new NotActivatedException(); + case 0x6985: + // conditions of use not satisfied + throw new NotActivatedException(); + + default: + String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW()); + log.info(msg); + throw new SignatureCardException(msg); + } + + } + + protected byte[] execSELECT_FID(CardChannel channel, byte[] fid) + throws SignatureCardException, CardException { + + ResponseAPDU resp = channel.transmit( + new CommandAPDU(0x00, 0xA4, 0x02, 0x0C, fid, 256)); + + if (resp.getSW() == 0x6A82) { + String msg = "File or application not found FID=" + + SMCCHelper.toString(fid) + " SW=" + + Integer.toHexString(resp.getSW()) + "."; + log.info(msg); + throw new FileNotFoundException(msg); + } else if (resp.getSW() != 0x9000) { + String msg = "Failed to select application FID=" + + SMCCHelper.toString(fid) + " SW=" + + Integer.toHexString(resp.getSW()) + "."; + log.error(msg); + throw new SignatureCardException(msg); + } else { + return resp.getBytes(); + } + + } + + protected void execMSE(CardChannel channel, int p1, int p2, byte[] data) + throws CardException, SignatureCardException { + ResponseAPDU resp = channel.transmit( + new CommandAPDU(0x00, 0x22, p1, p2, data, 256)); + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("MSE:SET failed: SW=" + + Integer.toHexString(resp.getSW())); + } + } + + protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel, byte[] hash) + throws CardException, SignatureCardException { + ResponseAPDU resp; + resp = channel.transmit( + new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, hash, 256)); + if (resp.getSW() == 0x6982) { + throw new SecurityStatusNotSatisfiedException(); + } else if (resp.getSW() == 0x6983) { + throw new LockedException(); + } else if (resp.getSW() != 0x9000) { + throw new SignatureCardException( + "PSO: COMPUTE DIGITAL SIGNATRE failed: SW=" + + Integer.toHexString(resp.getSW())); + } else { + return resp.getData(); + } + } + + + + +} \ No newline at end of file diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java new file mode 100644 index 00000000..831a1f9b --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java @@ -0,0 +1,297 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.util.ISO7816Utils; +import at.gv.egiz.smcc.util.SMCCHelper; + +public class ITCard extends AbstractSignatureCard { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(STARCOSCard.class); + + public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; + + public static final byte[] DF1 = new byte[] { (byte) 0x11, (byte) 0x00 }; + + public static final byte[] EF_C_Carta = new byte[] { (byte) 0x11, (byte) 0x01 }; + + private static final PINSpec SS_PIN_SPEC = + new PINSpec(5, 8, "[0-9]", + "at/gv/egiz/smcc/ITCard", "sig.pin", (byte) 0x10, + new byte[] { (byte) 0x11, (byte) 0x00 }); + + /** + * Creates a new instance. + */ + public ITCard() { + super("at/gv/egiz/smcc/ITCard"); + pinSpecs.add(SS_PIN_SPEC); + } + + @Override + @Exclusive + public byte[] getCertificate(KeyboxName keyboxName) + throws SignatureCardException, InterruptedException { + + if (keyboxName != KeyboxName.SECURE_SIGNATURE_KEYPAIR) { + throw new IllegalArgumentException("Keybox " + keyboxName + + " not supported"); + } + + try { + CardChannel channel = getCardChannel(); + // SELECT MF + execSELECT_FID(channel, MF); + // SELECT application + execSELECT_FID(channel, DF1); + // SELECT EF_C_Carta + byte[] fcx = execSELECT_FID(channel, EF_C_Carta); + int maxsize = ISO7816Utils.getLengthFromFCx(fcx); + // READ BINARY + byte[] certificate = ISO7816Utils.readTransparentFileTLV(channel, maxsize, (byte) 0x30); + if (certificate == null) { + throw new NotActivatedException(); + } + return certificate; + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } catch (CardException e) { + log.info("Failed to get certificate.", e); + throw new SignatureCardException(e); + } + + } + + @Override + @Exclusive + public byte[] getInfobox(String infobox, PINProvider provider, String domainId) + throws SignatureCardException, InterruptedException { + + throw new IllegalArgumentException("Infobox '" + infobox + + "' not supported."); + } + + @Override + @Exclusive + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, + InterruptedException, IOException { + + if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { + throw new SignatureCardException("Card does not support key " + keyboxName + "."); + } + if (!"http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) { + throw new SignatureCardException("Card does not support algorithm " + alg + "."); + } + + byte[] dst = new byte[] { + (byte) 0x83, // tag for algorithm reference + (byte) 0x01, // algorithm reference + (byte) 0x01 // private key reference + }; + + MessageDigest md; + try { + md = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get MessageDigest.", e); + throw new SignatureCardException(e); + } + // calculate message digest + byte[] digest = new byte[md.getDigestLength()]; + for (int l; (l = input.read(digest)) != -1;) { + md.update(digest, 0, l); + } + digest = md.digest(); + + try { + + CardChannel channel = getCardChannel(); + + // SELECT MF + execSELECT_FID(channel, MF); + // VERIFY + verifyPINLoop(channel, SS_PIN_SPEC, provider); + // MANAGE SECURITY ENVIRONMENT : RESTORE SE + execMSE(channel, 0xF3, 0x03, null); + // MANAGE SECURITY ENVIRONMENT : SET DST + execMSE(channel, 0xF1, 0xB8, dst); + // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest); + + } catch (CardException e) { + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); + } + + } + + protected void verifyPINLoop(CardChannel channel, PINSpec spec, + PINProvider provider) throws LockedException, NotActivatedException, + SignatureCardException, InterruptedException, CardException { + + int retries = -1; + do { + retries = verifyPIN(channel, spec, provider, retries); + } while (retries >= -1); + } + + protected int verifyPIN(CardChannel channel, PINSpec pinSpec, + PINProvider provider, int retries) throws SignatureCardException, + LockedException, NotActivatedException, InterruptedException, + CardException { + + VerifyAPDUSpec apduSpec = new VerifyAPDUSpec( + new byte[] { + (byte) 0x00, (byte) 0x20, (byte) 0x00, pinSpec.getKID(), (byte) 0x08, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }, + 0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8); + + ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); + + if (resp.getSW() == 0x9000) { + return -2; + } + if (resp.getSW() >> 4 == 0x63c) { + return 0x0f & resp.getSW(); + } + + switch (resp.getSW()) { + case 0x6300: + // incorrect PIN, number of retries not provided + return -1; + case 0x6983: + // authentication method blocked + throw new LockedException(); + case 0x6984: + // reference data not usable + throw new NotActivatedException(); + case 0x6985: + // conditions of use not satisfied + throw new NotActivatedException(); + + default: + String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW()); + log.info(msg); + throw new SignatureCardException(msg); + } + + } + + protected byte[] execSELECT_FID(CardChannel channel, byte[] fid) + throws SignatureCardException, CardException { + + ResponseAPDU resp = channel.transmit( + new CommandAPDU(0x00, 0xA4, 0x00, 0x00, fid, 256)); + + if (resp.getSW() == 0x6A82) { + String msg = "File or application not found FID=" + + SMCCHelper.toString(fid) + " SW=" + + Integer.toHexString(resp.getSW()) + "."; + log.info(msg); + throw new FileNotFoundException(msg); + } else if (resp.getSW() != 0x9000) { + String msg = "Failed to select application FID=" + + SMCCHelper.toString(fid) + " SW=" + + Integer.toHexString(resp.getSW()) + "."; + log.error(msg); + throw new SignatureCardException(msg); + } else { + return resp.getBytes(); + } + + } + + protected void execMSE(CardChannel channel, int p1, int p2, byte[] data) + throws CardException, SignatureCardException { + + ResponseAPDU resp; + if (data == null) { + resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2)); + } else { + resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2, data)); + } + + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("MSE:SET failed: SW=" + + Integer.toHexString(resp.getSW())); + } + } + + protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel, + byte[] hash) throws CardException, SignatureCardException { + + byte[] oid = new byte[] { (byte) 0x30, (byte) 0x21, (byte) 0x30, + (byte) 0x09, (byte) 0x06, (byte) 0x05, (byte) 0x2b, + (byte) 0x0e, (byte) 0x03, (byte) 0x02, (byte) 0x1a, + (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x14 }; + + ByteArrayOutputStream data = new ByteArrayOutputStream(); + + try { + // header + data.write(new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x01 }); + // padding + for (int i = 0, len = 125 - hash.length - oid.length; i < len; i++) { + data.write((byte) 0xFF); + } + data.write((byte) 0x00); + // oid + data.write(oid); + // hash + data.write(hash); + } catch (IOException e) { + throw new SignatureCardException(e); + } + + ResponseAPDU resp = channel + .transmit(new CommandAPDU(0x00, 0x2A, 0x80, 0x86, data.toByteArray(), 0x81)); + + + if (resp.getSW() == 0x6982) { + throw new SecurityStatusNotSatisfiedException(); + } else if (resp.getSW() == 0x6983) { + throw new LockedException(); + } else if (resp.getSW() != 0x9000) { + throw new SignatureCardException( + "PSO: COMPUTE DIGITAL SIGNATRE failed: SW=" + + Integer.toHexString(resp.getSW())); + } else { + return resp.getData(); + } +} + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java index a0c2391d..01de8a77 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -19,11 +19,16 @@ package at.gv.egiz.smcc; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.List; +import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; @@ -41,6 +46,8 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu private static Log log = LogFactory.getLog(STARCOSCard.class); public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; + + public static final byte[] EF_VERSION = new byte[] { (byte) 0x00, (byte) 0x32 }; /** * Application ID SV-Personendaten. @@ -106,19 +113,6 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu public static final byte[] EF_C_X509_CA_CS_DS = new byte[] { (byte) 0xc6, (byte) 0x08 }; - public static final byte[] DST_SS = new byte[] { (byte) 0x84, (byte) 0x03, // tag - // , - // length - // ( - // key - // desc - // . - // ) - (byte) 0x80, (byte) 0x02, (byte) 0x00, // local, key ID, key version - (byte) 0x89, (byte) 0x03, // tag, length (algorithm ID) - (byte) 0x13, (byte) 0x35, (byte) 0x10 // ECDSA - }; - public static final byte KID_PIN_SS = (byte) 0x81; // Gewöhnliche Signatur (GS) @@ -133,19 +127,6 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu public static final byte[] EF_C_X509_CA_CS = new byte[] { (byte) 0x2f, (byte) 0x02 }; - public static final byte[] DST_GS = new byte[] { (byte) 0x84, (byte) 0x03, // tag - // , - // length - // ( - // key - // desc - // . - // ) - (byte) 0x80, (byte) 0x02, (byte) 0x00, // local, key ID, key version - (byte) 0x89, (byte) 0x03, // tag, length (algorithm ID) - (byte) 0x13, (byte) 0x35, (byte) 0x10 // ECDSA - }; - public static final byte KID_PIN_CARD = (byte) 0x01; private static final PINSpec CARD_PIN_SPEC = @@ -155,9 +136,11 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu private static final PINSpec SS_PIN_SPEC = new PINSpec(6, 12, "[0-9]", "at/gv/egiz/smcc/STARCOSCard", "sig.pin", KID_PIN_SS, AID_DF_SS); + + protected double version = 1.1; /** - * Creates an new instance. + * Creates a new instance. */ public STARCOSCard() { super("at/gv/egiz/smcc/STARCOSCard"); @@ -165,6 +148,35 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu pinSpecs.add(SS_PIN_SPEC); } + /* (non-Javadoc) + * @see at.gv.egiz.smcc.AbstractSignatureCard#init(javax.smartcardio.Card, javax.smartcardio.CardTerminal) + */ + @Override + public void init(Card card, CardTerminal cardTerminal) { + super.init(card, cardTerminal); + + // determine application version + CardChannel channel = getCardChannel(); + try { + // SELECT MF + execSELECT_MF(channel); + // SELECT EF_VERSION + execSELECT_FID(channel, EF_VERSION); + // READ BINARY + byte[] ver = ISO7816Utils.readRecord(channel, 1); + if (ver[0] == (byte) 0xa5 && ver[2] == (byte) 0x53) { + version = (0x0F & ver[4]) + (0xF0 & ver[5])/160.0 + (0x0F & ver[5])/100.0; + String generation = (version < 1.2) ? "<= G2" : "G3"; + log.info("e-card version=" + version + " (" + generation + ")"); + } + } catch (CardException e) { + log.warn(e); + } catch (SignatureCardException e) { + log.warn(e); + } + + } + @Override @Exclusive public byte[] getCertificate(KeyboxName keyboxName) @@ -281,19 +293,57 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu @Override @Exclusive - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, - PINProvider provider) throws SignatureCardException, InterruptedException { + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { - if (hash.length != 20) { - throw new IllegalArgumentException("Hash value must be of length 20."); + ByteArrayOutputStream dst = new ByteArrayOutputStream(); + byte[] ht = null; + + MessageDigest md = null; + try { + if (version < 1.2 && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1".equals(alg)) { + // local key ID '02' version '00' + dst.write(new byte[] {(byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00}); + // algorithm ID ECDSA with SHA-1 + dst.write(new byte[] {(byte) 0x89, (byte) 0x03, (byte) 0x13, (byte) 0x35, (byte) 0x10}); + md = MessageDigest.getInstance("SHA-1"); + } else if (version >= 1.2 && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256".equals(alg)) { + // local key ID '02' version '00' + dst.write(new byte[] {(byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00}); + // portable algorithm reference + dst.write(new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x04}); + // hash template + ht = new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x40}; + md = MessageDigest.getInstance("SHA256"); + } else if (version >= 1.2 && "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256".equals(alg)) { + // local key ID '03' version '00' + dst.write(new byte[] {(byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x03, (byte) 0x00}); + // portable algorithm reference + dst.write(new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x02}); + // hash template + ht = new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x40}; + md = MessageDigest.getInstance("SHA256"); + } else { + throw new SignatureCardException("e-card versio " + version + " does not support signature algorithm " + alg + "."); + } + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get MessageDigest.", e); + throw new SignatureCardException(e); } - + + // calculate message digest + byte[] digest = new byte[md.getDigestLength()]; + for (int l; (l = input.read(digest)) != -1;) { + md.update(digest, 0, l); + } + digest = md.digest(); + try { CardChannel channel = getCardChannel(); if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { - + PINSpec spec = SS_PIN_SPEC; // SELECT MF @@ -303,11 +353,21 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu // VERIFY verifyPINLoop(channel, spec, provider); // MANAGE SECURITY ENVIRONMENT : SET DST - execMSE(channel, 0x41, 0xb6, DST_SS); - // PERFORM SECURITY OPERATION : HASH - execPSO_HASH(channel, hash); - // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE - return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel); + execMSE(channel, 0x41, 0xb6, dst.toByteArray()); + if (ht != null) { + // PERFORM SECURITY OPERATION : SET HT + execMSE(channel, 0x41, 0xaa, ht); + } + if (version < 1.2) { + // PERFORM SECURITY OPERATION : HASH + execPSO_HASH(channel, digest); + // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, null); + } else { + // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest); + } + } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { @@ -316,14 +376,17 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu // SELECT application execSELECT_AID(channel, AID_DF_GS); // MANAGE SECURITY ENVIRONMENT : SET DST - execMSE(channel, 0x41, 0xb6, DST_GS); + execMSE(channel, 0x41, 0xb6, dst.toByteArray()); + if (ht != null) { + // PERFORM SECURITY OPERATION : SET HT + execMSE(channel, 0x41, 0xaa, ht); + } // PERFORM SECURITY OPERATION : HASH - execPSO_HASH(channel, hash); - + execPSO_HASH(channel, digest); while (true) { try { // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE - return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel); + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, null); } catch (SecurityStatusNotSatisfiedException e) { verifyPINLoop(channel, spec, provider); } @@ -682,7 +745,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu ResponseAPDU resp = channel.transmit( new CommandAPDU(0x00, 0x22, p1, p2, data)); if (resp.getSW() != 0x9000) { - throw new SignatureCardException("MSE:SET DST failed: SW=" + throw new SignatureCardException("MSE:SET failed: SW=" + Integer.toHexString(resp.getSW())); } } @@ -701,10 +764,47 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu } } - protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel) + protected void execPSO_HASH(CardChannel channel, InputStream input) + throws SignatureCardException, CardException { + ResponseAPDU resp; + int blockSize = 64; + byte[] b = new byte[blockSize]; + try { + ByteArrayOutputStream data = new ByteArrayOutputStream(); + // initialize + data.write((byte) 0x90); + data.write((byte) 0x00); + resp = channel.transmit( + new CommandAPDU(0x10, 0x2A, 0x90, 0xA0, data.toByteArray())); + data.reset(); + for (int l; (l = input.read(b)) != -1;) { + data.write((byte) 0x80); + data.write(l); + data.write(b, 0, l); + resp = channel.transmit( + new CommandAPDU((l == blockSize) ? 0x10 : 0x00, 0x2A, 0x90, 0xA0, data.toByteArray())); + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("PSO:HASH failed: SW=" + + Integer.toHexString(resp.getSW())); + } + data.reset(); + } + } catch (IOException e) { + throw new SignatureCardException(e); + } + + } + + protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel, byte[] hash) throws CardException, SignatureCardException { - ResponseAPDU resp = channel.transmit( - new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 256)); + ResponseAPDU resp; + if (hash != null) { + resp = channel.transmit( + new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, hash, 256)); + } else { + resp = channel.transmit( + new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 256)); + } if (resp.getSW() == 0x6982) { throw new SecurityStatusNotSatisfiedException(); } else if (resp.getSW() == 0x6983) { diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java index 279362c0..670704d5 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -20,6 +20,7 @@ import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.security.InvalidKeyException; @@ -308,7 +309,7 @@ public class SWCard implements SignatureCard { } @Override - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, PINProvider provider) throws SignatureCardException, InterruptedException { + public byte[] createSignature(InputStream input, KeyboxName keyboxName, PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { // KeyStore password char[] password = getPassword(keyboxName); @@ -363,7 +364,10 @@ public class SWCard implements SignatureCard { try { Signature signature = Signature.getInstance(algorithm); signature.initSign(privateKey); - signature.update(hash); + int l; + for (byte[] b = new byte[20]; (l = input.read(b)) != -1;) { + signature.update(b, 0, l); + } return signature.sign(); } catch (NoSuchAlgorithmException e) { String msg = "Algorithm + '" + algorithm + "' not supported for signing."; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index 1a163783..3d56f97b 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -18,6 +18,9 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.ccid.CCID; + +import java.io.IOException; +import java.io.InputStream; import java.util.Locale; import javax.smartcardio.Card; @@ -101,15 +104,17 @@ public interface SignatureCard { /** * - * @param hash + * @param input * @param keyboxName * @param provider + * @param alg TODO * @return * @throws at.gv.egiz.smcc.SignatureCardException * @throws java.lang.InterruptedException if applet is destroyed while in pin dialog + * @throws IOException */ - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, - PINProvider provider) throws SignatureCardException, InterruptedException; + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException; public CCID getReader(); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java index 26844473..47053f98 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java @@ -170,21 +170,21 @@ public class SignatureCardFactory { }, "at.gv.egiz.smcc.STARCOSCard")); -// // e-card G3 -// supportedCards.add(new SupportedCard( -// // ATR (3b:dd:96:ff:81:b1:fe:45:1f:03:80:31:b0:52:02:03:64:04:1b:b4:22:81:05:18) -// new byte[] { -// (byte) 0x3b, (byte) 0xdd, (byte) 0x96, (byte) 0xff, (byte) 0x81, (byte) 0xb1, (byte) 0xfe, (byte) 0x45, -// (byte) 0x1f, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, -// (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 -// }, -// // mask ( -// new byte[] { -// (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, -// (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, -// (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 -// }, -// "at.gv.egiz.smcc.STARCOSCard")); + // e-card G3 + supportedCards.add(new SupportedCard( + // ATR (3b:dd:96:ff:81:b1:fe:45:1f:03:80:31:b0:52:02:03:64:04:1b:b4:22:81:05:18) + new byte[] { + (byte) 0x3b, (byte) 0xdd, (byte) 0x96, (byte) 0xff, (byte) 0x81, (byte) 0xb1, (byte) 0xfe, (byte) 0x45, + (byte) 0x1f, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 + }, + // mask ( + new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 + }, + "at.gv.egiz.smcc.STARCOSCard")); // a-sign premium supportedCards.add(new SupportedCard( @@ -202,6 +202,72 @@ public class SignatureCardFactory { }, "at.gv.egiz.smcc.ACOSCard")); + // BELPIC + supportedCards.add(new SupportedCard( + // ATR (3b:98:13:40:0A:A5:03:01:01:01:AD:13:11) + new byte[] { (byte) 0x3b, (byte) 0x98, (byte) 0x13, + (byte) 0x40, (byte) 0x0a, (byte) 0xa5, (byte) 0x03, + (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0xad, + (byte) 0x13, (byte) 0x11 }, + // mask (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff) + new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff }, + "at.gv.egiz.smcc.BELPICCard")); + + // ITCards + supportedCards.add(new SupportedCard( + // ATR = + // [3b:ff:18:00:ff:81:31:fe:55:00:6b:02:09:02:00:01:11:01:43:4e:53:11:31:80:8e] + new byte[] { (byte) 0x3b, (byte) 0xff, (byte) 0x18, + (byte) 0x00, (byte) 0xff, (byte) 0x81, (byte) 0x31, + (byte) 0xfe, (byte) 0x55, (byte) 0x00, (byte) 0x6b, + (byte) 0x02, (byte) 0x09 /* + * , (byte) 0x02, (byte) 0x00, + * (byte) 0x01, (byte) 0x11, + * (byte) 0x01, (byte) 0x43, + * (byte) 0x4e, (byte) 0x53, + * (byte) 0x11, (byte) 0x31, + * (byte) 0x80, (byte) 0x8e + */ + }, + // mask (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff) + new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff /* + * , (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff + */ + }, "at.gv.egiz.smcc.ITCard")); + supportedCards.add(new SupportedCard( + // ATR + // (3B:FF:18:00:FF:C1:0A:31:FE:55:00:6B:05:08:C8:05:01:01:01:43:4E:53:10:31:80:1C) + new byte[] { (byte) 0x3b, (byte) 0xff, (byte) 0x18, + (byte) 0x00, (byte) 0xFF, (byte) 0xC1, (byte) 0x0a, + (byte) 0x31, (byte) 0xfe, (byte) 0x55, (byte) 0x00, + (byte) 0x6B, (byte) 0x05, (byte) 0x08, (byte) 0xC8, + (byte) 0x05, (byte) 0x01, (byte) 0x01, (byte) 0x01, + (byte) 0x43, (byte) 0x4E, (byte) 0x53, (byte) 0x10, + (byte) 0x31, (byte) 0x80, (byte) 0x1C }, + // mask + // (ff:ff:ff:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00) + new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff }, + "at.gv.egiz.smcc.ITCard")); + + + } /** diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java b/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java index c5c7cbc9..fcd0b876 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java @@ -103,6 +103,14 @@ public class ISO7816Utils { TransparentFileInputStream is = openTransparentFileInputStream(channel, maxSize); + + return readTransparentFileTLV(is, maxSize, expectedType); + + } + + public static byte[] readTransparentFileTLV(TransparentFileInputStream is, int maxSize, + byte expectedType) throws CardException, SignatureCardException { + try { @@ -170,7 +178,8 @@ public class ISO7816Utils { while (pos < (fcx[1] - 2)) { switch (fcx[pos]) { - case (byte) 0x80: { + case (byte) 0x80: + case (byte) 0x81: { len = 0xFF & fcx[pos + 2]; for (int i = 1; i < fcx[pos + 1]; i++) { len<<=8; diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties new file mode 100644 index 00000000..71267394 --- /dev/null +++ b/smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties @@ -0,0 +1,3 @@ +#pin.name=PIN +sig.pin.name=PIN +sig.pin.length=4-12 \ No newline at end of file diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties new file mode 100644 index 00000000..e0222a70 --- /dev/null +++ b/smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties @@ -0,0 +1,3 @@ +#pin.name=PIN +sig.pin.name=PIN +sig.pin.length=5-8 \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java index 2a55357d..b3bd07ab 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java @@ -18,6 +18,8 @@ package at.gv.egiz.smcc; import static org.junit.Assert.*; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -178,13 +180,10 @@ public abstract class CardTest { @Test(expected = CancelledException.class) public void testSignSIGCancel() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -193,21 +192,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, pinProvider, + null); } @Test(expected = CancelledException.class) public void testSignDECCancel() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -216,21 +213,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } @Test(expected = InterruptedException.class) public void testSignSIGInterrrupted() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -239,21 +234,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = InterruptedException.class) public void testSignDECInterrrupted() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -262,21 +255,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } @Test(expected = CancelledException.class) public void testSignSIGConcurrent() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { final SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -294,21 +285,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = CancelledException.class) public void testSignDECConcurrent() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { final SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -326,8 +315,9 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java index 90bb039e..56d1e4b2 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java @@ -21,6 +21,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -125,7 +127,7 @@ public abstract class ACOSCardTest extends CardTest { @Test public void testSignSIG() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { char[] pin = "123456".toCharArray(); @@ -134,11 +136,9 @@ public abstract class ACOSCardTest extends CardTest { ACOSApplSIG appl = (ACOSApplSIG) card.getApplication(ACOSAppl.AID_SIG); appl.setPin(ACOSApplSIG.KID_PIN_SIG, pin); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - - byte[] signature = signatureCard.createSignature(hash, - KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin)); + byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), + KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); assertNotNull(signature); @@ -147,7 +147,7 @@ public abstract class ACOSCardTest extends CardTest { @Test public void testSignDEC() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { char[] pin = "1234".toCharArray(); @@ -156,11 +156,9 @@ public abstract class ACOSCardTest extends CardTest { ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC); appl.setPin(ACOSApplDEC.KID_PIN_DEC, pin); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - - byte[] signature = signatureCard.createSignature(hash, - KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin)); + byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), + KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); assertNotNull(signature); @@ -169,74 +167,66 @@ public abstract class ACOSCardTest extends CardTest { @Test(expected = LockedException.class) public void testSignSIGInvalidPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignDECInvalidPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignSIGBlockedPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); CardEmul card = (CardEmul) signatureCard.getCard(); ACOSApplSIG appl = (ACOSApplSIG) card.getApplication(ACOSAppl.AID_SIG); appl.setPin(ACOSApplSIG.KID_PIN_SIG, null); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignDECBlockedPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); CardEmul card = (CardEmul) signatureCard.getCard(); ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC); appl.setPin(ACOSApplDEC.KID_PIN_DEC, null); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java index 89e2ca65..b7dc9a0c 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -147,7 +149,7 @@ public class STARCOSCardTest extends CardTest { @Test public void testSignSichereSignatur() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { char[] pin = "123456".toCharArray(); @@ -156,11 +158,9 @@ public class STARCOSCardTest extends CardTest { STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, pin); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - - byte[] signature = signatureCard.createSignature(hash, - KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin)); + byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), + KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); assertNotNull(signature); @@ -169,7 +169,7 @@ public class STARCOSCardTest extends CardTest { @Test public void testSignGewoehnlicheSignatur() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { char[] pin = "1234".toCharArray(); @@ -178,11 +178,9 @@ public class STARCOSCardTest extends CardTest { STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, pin); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - - byte[] signature = signatureCard.createSignature(hash, - KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin)); + byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), + KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); assertNotNull(signature); @@ -191,75 +189,67 @@ public class STARCOSCardTest extends CardTest { @Test(expected = LockedException.class) public void testSignSichereSignaturInvalidPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignGewoehnlicheSignaturInvalidPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("1234".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignSichereSignaturBlockedPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); CardEmul card = (CardEmul) signatureCard.getCard(); STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, null); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); assertTrue(pinProvider.getProvided() <= 0); - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignGewoehnlicheSignaturBlockedPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); CardEmul card = (CardEmul) signatureCard.getCard(); STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, null); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 560f1373..58d7b305 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -18,9 +18,8 @@ package at.gv.egiz.bku.smccstal; import at.gv.egiz.bku.gui.BKUGUIFacade; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; @@ -44,7 +43,6 @@ import at.gv.egiz.stal.SignRequest; import at.gv.egiz.stal.SignResponse; import at.gv.egiz.stal.signedinfo.ObjectFactory; import at.gv.egiz.stal.signedinfo.SignedInfoType; -import at.gv.egiz.stal.util.JCEAlgorithmNames; public class SignRequestHandler extends AbstractRequestHandler { @@ -77,18 +75,11 @@ public class SignRequestHandler extends AbstractRequestHandler { JAXBElement si = (JAXBElement) unmarshaller.unmarshal(is); String signatureMethod = si.getValue().getSignatureMethod().getAlgorithm(); log.debug("Found signature method: " + signatureMethod); - String jceName = JCEAlgorithmNames.getJCEHashName(signatureMethod); - if (jceName == null) { - log.error("Hash algorithm not supported:"); - return new ErrorResponse(4006); - } - MessageDigest md = MessageDigest.getInstance(jceName); - md.update(signReq.getSignedInfo()); KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); - byte[] resp = card.createSignature(md.digest(), kb, + byte[] resp = card.createSignature(new ByteArrayInputStream(signReq.getSignedInfo()), kb, new PINProviderFactory(card.getReader(), gui) - .getSignaturePINProvider(secureViewer, si.getValue())); + .getSignaturePINProvider(secureViewer, si.getValue()), signatureMethod); if (resp == null) { return new ErrorResponse(6001); } @@ -127,9 +118,9 @@ public class SignRequestHandler extends AbstractRequestHandler { } catch (JAXBException e) { log.error("Cannot unmarshall signed info", e); return new ErrorResponse(1000); - } catch (NoSuchAlgorithmException e) { - log.error(e); - return new ErrorResponse(1000); + } catch (IOException e) { + log.error("Error while creating signature: " + e); + return new ErrorResponse(4000); } } else { log.fatal("Got unexpected STAL request: " + request); diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java index 36880e68..16d3efa9 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -1,5 +1,6 @@ package at.gv.egiz.smcc; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -37,8 +38,8 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements signatureCard = new SignatureCard() { @Override - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, - PINProvider provider) throws SignatureCardException { + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException { // TODO Auto-generated method stub return null; } diff --git a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java index 82cba624..6f694b91 100644 --- a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java +++ b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java @@ -104,14 +104,14 @@ public class QualifyingPropertiesFactory { } - public DigestAlgAndValueType createDigestAlgAndValueType(X509Certificate certificate) throws QualifyingPropertiesException { + public DigestAlgAndValueType createDigestAlgAndValueType(X509Certificate certificate, DigestMethod dm) throws QualifyingPropertiesException { DigestMethodType digestMethodType = dsFactory.createDigestMethodType(); - digestMethodType.setAlgorithm(DigestMethod.SHA1); - + digestMethodType.setAlgorithm(dm.getAlgorithm()); + byte[] digest; try { - MessageDigest messageDigest = MessageDigest.getInstance("SHA-1"); + MessageDigest messageDigest = MessageDigest.getInstance(dm.getAlgorithm()); digest = messageDigest.digest(certificate.getEncoded()); } catch (CertificateEncodingException e) { throw new QualifyingPropertiesException(e); @@ -155,7 +155,10 @@ public class QualifyingPropertiesFactory { return dataObjectFormatType; } - public JAXBElement createQualifyingProperties111(String target, Date signingTime, List certificates, String idValue, List dataObjectFormats) throws QualifyingPropertiesException { + public JAXBElement createQualifyingProperties111( + String target, Date signingTime, List certificates, + String idValue, List dataObjectFormats, + DigestMethod digestMethod) throws QualifyingPropertiesException { GregorianCalendar gregorianCalendar = new GregorianCalendar(); gregorianCalendar.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -175,7 +178,7 @@ public class QualifyingPropertiesFactory { for (X509Certificate certificate : certificates) { CertIDType certIDType = qpFactory.createCertIDType(); - certIDType.setCertDigest(createDigestAlgAndValueType(certificate)); + certIDType.setCertDigest(createDigestAlgAndValueType(certificate, digestMethod)); certIDType.setIssuerSerial(createX509IssuerSerialType(certificate)); certIDs.add(certIDType); -- cgit v1.2.3 From 3da4655d011dfc2f04f9e4ac28b38aee42d01bc0 Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 5 Jan 2010 10:06:47 +0000 Subject: Features [#437] Handle pinpad [64:03] response apdu correctly [#445] pin entry feedback for VERIFY_PIN_START/FINISH [#471] Provide SecureViewer Link before Pinpad PinEntry timeout starts Bugs [#479] PIN Managment Applet allows unmatching new pin and pin confirmation [#480] PIN Management displays blocked PINs as ACTIVE [#486] Not possible to select 3 times in series the same item from signedReferencesList for display in secureViewer [#506] change pin dialog (gui) issues [#508] e-card G3 PIN activation (with TransportPIN) not supported [#509] closing secure viewer window (WINDOW_CLOSING) leaves "signature data is displayed in viewer" dialog in applet git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@565 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 28 +- .../main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java | 765 +++++++++------------ .../main/java/at/gv/egiz/bku/gui/PinDocument.java | 125 +--- .../at/gv/egiz/bku/gui/SecureViewerDialog.java | 118 ++-- .../at/gv/egiz/bku/gui/Messages.properties | 9 +- .../at/gv/egiz/bku/gui/Messages_en.properties | 9 +- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 13 +- .../at/gv/egiz/bku/gui/ComparePinDocument.java | 102 +++ .../at/gv/egiz/bku/gui/ExtendedPinDocument.java | 108 +++ .../java/at/gv/egiz/bku/gui/PINManagementGUI.java | 163 +++-- .../at/gv/egiz/bku/gui/PINManagementGUIFacade.java | 66 +- .../gv/egiz/bku/gui/ActivationMessages.properties | 36 +- .../egiz/bku/gui/ActivationMessages_en.properties | 34 +- BKUOnline/src/main/resources/log4j.properties | 2 +- BKUOnline/src/main/webapp/META-INF/context.xml | 2 +- smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 44 +- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 14 +- smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java | 11 +- .../java/at/gv/egiz/smcc/ChangePINProvider.java | 36 - smcc/src/main/java/at/gv/egiz/smcc/ITCard.java | 11 +- .../at/gv/egiz/smcc/PINConfirmationException.java | 19 - .../java/at/gv/egiz/smcc/PINFormatException.java | 19 - .../java/at/gv/egiz/smcc/PINMgmtSignatureCard.java | 11 +- .../src/main/java/at/gv/egiz/smcc/PINProvider.java | 45 -- .../at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java | 38 + .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 208 +++--- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 106 +-- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 9 +- .../java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java | 36 + .../at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java | 48 ++ .../main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java | 42 ++ .../java/at/gv/egiz/smcc/pin/gui/PINProvider.java | 49 ++ .../java/at/gv/egiz/smcc/reader/CardReader.java | 92 +++ .../at/gv/egiz/smcc/reader/DefaultCardReader.java | 106 +++ .../at/gv/egiz/smcc/reader/PinpadCardReader.java | 703 +++++++++++++++++++ .../java/at/gv/egiz/smcc/reader/ReaderFactory.java | 128 ++++ .../test/java/at/gv/egiz/smcc/AbstractAppl.java | 1 + smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java | 14 +- smcc/src/test/java/at/gv/egiz/smcc/CardTest.java | 171 +---- smcc/src/test/java/at/gv/egiz/smcc/PIN.java | 10 +- .../test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java | 2 +- .../java/at/gv/egiz/smcc/acos/A03CardEmul.java | 7 +- .../java/at/gv/egiz/smcc/acos/A03CardTest.java | 9 +- .../java/at/gv/egiz/smcc/acos/A04CardEmul.java | 7 +- .../java/at/gv/egiz/smcc/acos/A04CardTest.java | 12 +- .../java/at/gv/egiz/smcc/acos/ACOSApplDEC.java | 2 +- .../java/at/gv/egiz/smcc/acos/ACOSApplSIG.java | 2 +- .../java/at/gv/egiz/smcc/acos/ACOSCardTest.java | 21 +- .../egiz/smcc/pin/gui/CancelChangePINProvider.java | 39 ++ .../at/gv/egiz/smcc/pin/gui/CancelPINProvider.java | 29 + .../at/gv/egiz/smcc/pin/gui/ChangePINProvider.java | 49 ++ .../at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java | 68 ++ .../java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java | 48 ++ .../gv/egiz/smcc/pin/gui/InterruptPINProvider.java | 34 + .../smcc/pin/gui/InvalidChangePINProvider.java | 56 ++ .../gv/egiz/smcc/pin/gui/InvalidPINProvider.java | 48 ++ .../gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java | 43 ++ .../java/at/gv/egiz/smcc/starcos/STARCOSAppl.java | 23 - .../starcos/STARCOSApplGewoehnlicheSignatur.java | 27 +- .../gv/egiz/smcc/starcos/STARCOSApplInfobox.java | 5 + .../smcc/starcos/STARCOSApplSichereSignatur.java | 36 +- .../egiz/smcc/starcos/STARCOSCardChannelEmul.java | 105 ++- .../at/gv/egiz/smcc/starcos/STARCOSCardEmul.java | 24 +- .../at/gv/egiz/smcc/starcos/STARCOSCardTest.java | 132 ++-- .../smcc/starcos/STARCOSG3CardChannelEmul.java | 46 ++ .../at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java | 57 ++ .../at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java | 119 ++++ smccSTAL/src/main/java/META-INF/MANIFEST.MF | 3 - .../gv/egiz/bku/pin/gui/AbstractPINProvider.java | 60 ++ .../java/at/gv/egiz/bku/pin/gui/SignPINGUI.java | 136 ++++ .../at/gv/egiz/bku/pin/gui/SignPINProvider.java | 105 +++ .../java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java | 76 ++ .../at/gv/egiz/bku/pin/gui/VerifyPINProvider.java | 72 ++ .../gv/egiz/bku/smccstal/AbstractPINProvider.java | 67 -- .../bku/smccstal/InfoBoxReadRequestHandler.java | 9 +- .../gv/egiz/bku/smccstal/PINProviderFactory.java | 327 --------- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 4 +- .../java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java | 13 +- .../at/gv/egiz/bku/pin/gui/ManagementPINGUI.java | 88 +++ .../gv/egiz/bku/pin/gui/ManagementPINProvider.java | 89 +++ .../bku/smccstal/ManagementPINProviderFactory.java | 246 ------- .../bku/smccstal/PINManagementRequestHandler.java | 210 ++++-- 82 files changed, 4011 insertions(+), 2095 deletions(-) create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ComparePinDocument.java create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ExtendedPinDocument.java delete mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java delete mode 100644 smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java delete mode 100644 smccSTAL/src/main/java/META-INF/MANIFEST.MF create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java create mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java delete mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java delete mode 100644 smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java create mode 100644 smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINGUI.java create mode 100644 smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINProvider.java delete mode 100644 smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java (limited to 'smccSTAL/src') diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index 91c91dcb..1e23c64c 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -16,7 +16,7 @@ */ package at.gv.egiz.bku.gui; -import at.gv.egiz.stal.HashDataInput; + import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.smcc.PINSpec; import java.awt.Color; import java.awt.event.ActionListener; @@ -53,14 +53,15 @@ public interface BKUGUIFacade { public static final String TITLE_WELCOME = "title.welcome"; public static final String TITLE_INSERTCARD = "title.insertcard"; public static final String TITLE_CARD_NOT_SUPPORTED = "title.cardnotsupported"; - public static final String TITLE_CARDPIN = "title.cardpin"; + public static final String TITLE_VERIFY_PIN = "title.verify.pin"; public static final String TITLE_SIGN = "title.sign"; + public static final String TITLE_VERIFY_PINPAD = "title.verify.pinpad"; public static final String TITLE_ERROR = "title.error"; public static final String TITLE_WARNING = "title.warning"; public static final String TITLE_ENTRY_TIMEOUT = "title.entry.timeout"; public static final String TITLE_RETRY = "title.retry"; public static final String TITLE_WAIT = "title.wait"; - public static final String TITLE_HASHDATA = "title.hashdata"; + public static final String TITLE_SIGNATURE_DATA = "title.signature.data"; public static final String WINDOWTITLE_SAVE = "windowtitle.save"; public static final String WINDOWTITLE_ERROR = "windowtitle.error"; public static final String WINDOWTITLE_SAVEDIR = "windowtitle.savedir"; @@ -75,6 +76,7 @@ public interface BKUGUIFacade { public static final String MESSAGE_CARD_NOT_SUPPORTED = "cardnotsupported"; public static final String MESSAGE_ENTERPIN = "enterpin"; public static final String MESSAGE_ENTERPIN_PINPAD = "enterpin.pinpad"; + public static final String MESSAGE_ENTERPIN_PINPAD_DIRECT = "enterpin.pinpad.direct"; public static final String MESSAGE_HASHDATALINK = "hashdatalink"; public static final String MESSAGE_HASHDATALINK_TINY = "hashdatalink.tiny"; public static final String MESSAGE_HASHDATALINK_FOCUS = "hashdatalink.focus"; @@ -96,8 +98,9 @@ public interface BKUGUIFacade { public static final String HELP_WAIT = "help.wait"; public static final String HELP_CARDNOTSUPPORTED = "help.cardnotsupported"; public static final String HELP_INSERTCARD = "help.insertcard"; - public static final String HELP_CARDPIN = "help.cardpin"; + public static final String HELP_VERIFY_PIN = "help.cardpin"; public static final String HELP_SIGNPIN = "help.signpin"; + public static final String HELP_PINPAD = "help.pinpad"; public static final String HELP_RETRY = "help.retry"; public static final String HELP_HASHDATA = "help.hashdata"; public static final String HELP_HASHDATALIST = "help.hashdatalist"; @@ -111,6 +114,18 @@ public interface BKUGUIFacade { public static final String SAVE_HASHDATAINPUT_PREFIX = "save.hashdatainput.prefix"; public static final String ALT_HELP = "alt.help"; + public void showEnterPINDirect(PINSpec spec, int retries); + + public void showEnterPIN(PINSpec spec, int retries); + + public void showSignatureDataDialog(PINSpec spec, ActionListener listener, String string, ActionListener aThis0, String string0, ActionListener aThis1, String string1); + + public void correctionButtonPressed(); + + public void allKeysCleared(); + + public void validKeyPressed(); + public enum Style { tiny, simple, advanced }; /** @@ -119,7 +134,7 @@ public interface BKUGUIFacade { */ public Locale getLocale(); - public void showCardPINDialog(PINSpec pinSpec, int numRetries, + public void showVerifyPINDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); @@ -128,9 +143,6 @@ public interface BKUGUIFacade { ActionListener cancelListener, String cancelCommand, ActionListener viewerListener, String viewerCommand); - public void showPinpadSignaturePINDialog(PINSpec pinSpec, int numRetries, - ActionListener viewerListener, String viewerCommand); - public char[] getPin(); /** diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java index baffb3fd..3fc631c3 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -93,6 +93,7 @@ public class BKUGUIImpl implements BKUGUIFacade { protected JLabel switchFocusDummyLabel; /** remember the pinfield to return to worker */ protected JPasswordField pinField; + protected JPasswordField pinpadPINField; protected int buttonSize; @@ -360,221 +361,27 @@ public class BKUGUIImpl implements BKUGUIFacade { return messages.containsKey(key); } -// @Override -// public void showWelcomeDialog() { -// -// log.debug("scheduling welcome dialog"); -// -// SwingUtilities.invokeLater(new Runnable() { -// -// @Override -// public void run() { -// -// log.debug("show welcome dialog"); -// -// mainPanel.removeAll(); -// buttonPanel.removeAll(); -// -// helpListener.setHelpTopic(HELP_WELCOME); -// -// JLabel welcomeMsgLabel = new JLabel(); -// welcomeMsgLabel.setFont(welcomeMsgLabel.getFont().deriveFont(welcomeMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); -// -// if (renderHeaderPanel) { -// titleLabel.setText(getMessage(TITLE_WELCOME)); -// welcomeMsgLabel.setText(getMessage(MESSAGE_WAIT)); -// } else { -// welcomeMsgLabel.setText(getMessage(TITLE_WELCOME)); -// } -// -// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); -// mainPanel.setLayout(mainPanelLayout); -// -// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() -// .addComponent(welcomeMsgLabel); -// GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addComponent(welcomeMsgLabel); -// if (!renderHeaderPanel) { -// messageHorizontal -// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) -// .addComponent(helpLabel); -// messageVertical -// .addComponent(helpLabel); -// } -// -// mainPanelLayout.setHorizontalGroup(messageHorizontal); -// mainPanelLayout.setVerticalGroup(messageVertical); -// -// contentPanel.validate(); -// -// } -// }); -// } - -// @Override -// public void showInsertCardDialog( -// final ActionListener cancelListener, final String cancelCommand) { -// -// log.debug("scheduling insert card dialog"); -// -// SwingUtilities.invokeLater(new Runnable() { -// -// @Override -// public void run() { -// -// log.debug("show insert card dialog"); -// -// mainPanel.removeAll(); -// buttonPanel.removeAll(); -// -// if (renderHeaderPanel) { -// titleLabel.setText(getMessage(TITLE_INSERTCARD)); -// } -// -// helpListener.setHelpTopic(HELP_INSERTCARD); -// -// JLabel insertCardMsgLabel = new JLabel(); -// insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); -// insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); -// -// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); -// mainPanel.setLayout(mainPanelLayout); -// -// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() -// .addComponent(insertCardMsgLabel); -// GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup() -// .addComponent(insertCardMsgLabel); -// -// if (!renderHeaderPanel) { -// messageHorizontal -// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) -// .addComponent(helpLabel); -// messageVertical -// .addComponent(helpLabel); -// } -// -// mainPanelLayout.setHorizontalGroup(messageHorizontal); -// mainPanelLayout.setVerticalGroup(messageVertical); -// -// if (renderCancelButton) { -// JButton cancelButton = new JButton(); -// cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); -// cancelButton.setText(getMessage(BUTTON_CANCEL)); -// cancelButton.addActionListener(cancelListener); -// cancelButton.setActionCommand(cancelCommand); -// -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// buttonPanelLayout.setHorizontalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); -// buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addComponent(cancelButton)); -// } -// -// contentPanel.validate(); -// } -// }); -// } - - /** - * only difference to showInsertCard: title text: card not supported - * @param cancelListener - * @param cancelCommand - */ -// @Override -// public void showCardNotSupportedDialog(final ActionListener cancelListener, final String cancelCommand) { -// -// log.debug("scheduling card not supported dialog"); -// -// SwingUtilities.invokeLater(new Runnable() { -// -// @Override -// public void run() { -// -// log.debug("show card not supported dialog"); -// -// mainPanel.removeAll(); -// buttonPanel.removeAll(); -// -// JLabel insertCardMsgLabel = new JLabel(); -// insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); -// -// if (renderHeaderPanel) { -// titleLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); -// insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD)); -// } else { -// insertCardMsgLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED)); -// } -// -// helpListener.setHelpTopic(HELP_CARDNOTSUPPORTED); -// -// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); -// mainPanel.setLayout(mainPanelLayout); -// -// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() -// .addComponent(insertCardMsgLabel); -// GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addComponent(insertCardMsgLabel); -// if (!renderHeaderPanel) { -// messageHorizontal -// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) -// .addComponent(helpLabel); -// messageVertical -// .addComponent(helpLabel); -// } -// -// mainPanelLayout.setHorizontalGroup(messageHorizontal); -// mainPanelLayout.setVerticalGroup(messageVertical); -// -// if (renderCancelButton) { -// JButton cancelButton = new JButton(); -// cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); -// cancelButton.setText(getMessage(BUTTON_CANCEL)); -// cancelButton.addActionListener(cancelListener); -// cancelButton.setActionCommand(cancelCommand); -// -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// buttonPanelLayout.setHorizontalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) -// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); -// buttonPanelLayout.setVerticalGroup( -// buttonPanelLayout.createSequentialGroup() -// .addComponent(cancelButton)); -// } -// -// contentPanel.validate(); -// } -// }); -// } - @Override - public void showCardPINDialog(final PINSpec pinSpec, final int numRetries, + public void showVerifyPINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener okListener, final String okCommand, final ActionListener cancelListener, final String cancelCommand) { - log.debug("scheduling card-pin dialog"); + log.debug("scheduling verify pin dialog"); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - log.debug("[" + Thread.currentThread().getName() + "] show card-pin dialog"); + log.debug("[" + Thread.currentThread().getName() + "] show verify pin dialog"); mainPanel.removeAll(); buttonPanel.removeAll(); if (renderHeaderPanel) { if (numRetries < 0) { - String cardpinTitle = getMessage(TITLE_CARDPIN); - titleLabel.setText(MessageFormat.format(cardpinTitle, new Object[]{pinSpec.getLocalizedName()})); + String verifyTitle = getMessage(TITLE_VERIFY_PIN); + titleLabel.setText(MessageFormat.format(verifyTitle, new Object[]{pinSpec.getLocalizedName()})); } else { titleLabel.setText(getMessage(TITLE_RETRY)); } @@ -615,8 +422,8 @@ public class BKUGUIImpl implements BKUGUIFacade { } else { infoLabel.setText(MessageFormat.format(infoPattern, new Object[] {pinSpec.getLocalizedName()})); } - helpMouseListener.setHelpTopic(HELP_CARDPIN); - helpKeyListener.setHelpTopic(HELP_CARDPIN); + helpMouseListener.setHelpTopic(HELP_VERIFY_PIN); + helpKeyListener.setHelpTopic(HELP_VERIFY_PIN); } else { String retryPattern; if (numRetries < 2) { @@ -732,194 +539,346 @@ public class BKUGUIImpl implements BKUGUIFacade { }); } -// @Override -// public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { -// showCardPINDialog(pinSpec, -1, okListener, okCommand, cancelListener, cancelCommand); -// } -// -// @Override -// public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) { -// showCardPINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand); -// } + @Override + public void showEnterPINDirect(PINSpec pinSpec, int retries) { + if (retries < 0) { + showMessageDialog(TITLE_VERIFY_PINPAD, MESSAGE_ENTERPIN_PINPAD_DIRECT, new Object[] { + pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() }); + } else { + showMessageDialog(TITLE_RETRY, MESSAGE_RETRIES, new Object[]{String.valueOf(retries) }); + } + } -// @Override -// public void showSignaturePINDialog(PINSpec pinSpec, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand) { -// showSignaturePINDialog(pinSpec, -1, signListener, signCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); -// } + @Override + public void showEnterPIN(final PINSpec pinSpec, final int retries) { + showEnterPIN(pinSpec, retries, TITLE_VERIFY_PINPAD, MESSAGE_ENTERPIN_PINPAD, null); + } - @Override - public void showPinpadSignaturePINDialog(final PINSpec pinSpec, final int numRetries, -// final ActionListener cancelListener, final String cancelCommand, - final ActionListener hashdataListener, final String hashdataCommand) { + protected void showEnterPIN(final PINSpec pinSpec, final int retries, final String titleKey, final String messageKey, final Object[] messageParams) { + log.debug("scheduling pinpad dialog"); - log.debug("scheduling pinpad signature-pin dialog"); + SwingUtilities.invokeLater(new Runnable() { - SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { - @Override - public void run() { + log.debug("[" + Thread.currentThread().getName() + "] show pinpad dialog"); - log.debug("[" + Thread.currentThread().getName() + "] show pinpad signature-pin dialog"); + mainPanel.removeAll(); + buttonPanel.removeAll(); - mainPanel.removeAll(); - buttonPanel.removeAll(); + if (renderHeaderPanel) { + if (retries < 0) { + titleLabel.setText(getMessage(titleKey)); + } else { + titleLabel.setText(getMessage(TITLE_RETRY)); + } + } - if (renderHeaderPanel) { - if (numRetries < 0) { - titleLabel.setText(getMessage(TITLE_SIGN)); - } else { - titleLabel.setText(getMessage(TITLE_RETRY)); - } - } + final JLabel infoLabel = new JLabel(); + if (retries < 0) { + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + infoLabel.setText(MessageFormat.format(getMessage(messageKey), messageParams)); + helpMouseListener.setHelpTopic(HELP_PINPAD); + helpKeyListener.setHelpTopic(HELP_PINPAD); + } else { + String retryPattern; + if (retries == 1) { + retryPattern = getMessage(MESSAGE_LAST_RETRY); + } else { + retryPattern = getMessage(MESSAGE_RETRIES); + } + infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(retries)})); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); + infoLabel.setForeground(ERROR_COLOR); + helpMouseListener.setHelpTopic(HELP_RETRY); + helpKeyListener.setHelpTopic(HELP_RETRY); + } + + JLabel pinLabel = new JLabel(); + pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + String pinName = getMessage(LABEL_PIN); + pinLabel.setText(MessageFormat.format(pinName, new Object[]{pinSpec.getLocalizedName()})); + + pinpadPINField = new JPasswordField(); + pinpadPINField.setText(""); + pinpadPINField.setEnabled(false); + + JLabel pinsizeLabel = new JLabel(); + pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, pinsizeLabel.getFont().getSize()-2)); + pinsizeLabel.setText(MessageFormat.format(getMessage(LABEL_PINSIZE), pinSpec.getLocalizedLength())); + + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(infoLabel); + GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(infoLabel); + + if (!renderHeaderPanel) { + infoHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; + infoVertical + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; + } + + // align pinfield and pinsize to the right + GroupLayout.Group pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING); + GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup(); + + if (pinLabelPos == PinLabelPosition.ABOVE) { + pinHorizontal + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); + pinVertical + .addComponent(pinLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel); + } else { // PinLabelPosition.LEFT + pinHorizontal + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); + pinVertical + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(pinLabel) + .addComponent(pinpadPINField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel); + } + + mainPanelLayout.setHorizontalGroup( + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(infoHorizontal) + .addGroup(pinHorizontal)); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(infoVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pinVertical)); + + contentPanel.validate(); + } + }); + } + + @Override + public void showSignatureDataDialog(PINSpec spec, + final ActionListener enterPINListener, final String enterPINCommand, + final ActionListener cancelListener, final String cancelCommand, + final ActionListener hashdataListener, final String hashdataCommand) { + + log.debug("scheduling signature-data dialog"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("[" + Thread.currentThread().getName() + "] show signature-data dialog"); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + if (renderHeaderPanel) { + titleLabel.setText(getMessage(TITLE_SIGNATURE_DATA)); + } + + final JLabel infoLabel = new JLabel(); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); + } + infoLabel.setFocusable(true); + infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + infoLabel.setForeground(HYPERLINK_COLOR); + infoLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent me) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); + hashdataListener.actionPerformed(e); + } + }); + + infoLabel.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + + if(e.getKeyCode() == KeyEvent.VK_ENTER) { + ActionEvent e1 = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); + hashdataListener.actionPerformed(e1); + } + } + + }); + + infoLabel.addFocusListener(new FocusAdapter() { + + @Override + public void focusGained(FocusEvent e) { - final JLabel infoLabel = new JLabel(); - if (numRetries < 0) { - infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); if (shortText) { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); - } else { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); - } - infoLabel.setFocusable(true); - infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - infoLabel.setForeground(HYPERLINK_COLOR); - infoLabel.addMouseListener(new MouseAdapter() { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY_FOCUS)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_FOCUS)); + } + } - @Override - public void mouseClicked(MouseEvent me) { - ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); - hashdataListener.actionPerformed(e); - } - }); - - infoLabel.addKeyListener(new KeyAdapter() { - - @Override - public void keyPressed(KeyEvent e) { - - if(e.getKeyCode() == KeyEvent.VK_ENTER) { - ActionEvent e1 = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); - hashdataListener.actionPerformed(e1); - } - } - - }); - - infoLabel.addFocusListener(new FocusAdapter() { - - @Override - public void focusGained(FocusEvent e) { - - if (shortText) { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY_FOCUS)); - } else { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_FOCUS)); - } - } - - @Override - public void focusLost(FocusEvent e) { - - if (shortText) { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); - } else { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); - } - - } - - }); - - helpMouseListener.setHelpTopic(HELP_SIGNPIN); - helpKeyListener.setHelpTopic(HELP_SIGNPIN); - } else { - String retryPattern; - if (numRetries < 2) { - retryPattern = getMessage(MESSAGE_LAST_RETRY); - } else { - retryPattern = getMessage(MESSAGE_RETRIES); - } - infoLabel.setFocusable(true); - infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); - infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); - infoLabel.setForeground(ERROR_COLOR); - helpMouseListener.setHelpTopic(HELP_RETRY); - helpKeyListener.setHelpTopic(HELP_RETRY); - } + @Override + public void focusLost(FocusEvent e) { - String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD); - String msg = MessageFormat.format(msgPattern, new Object[] { - pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() }); + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); + } - JLabel msgLabel = new JLabel(); - msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD)); - msgLabel.setText(msg); + } - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); + }); - GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(infoLabel); - GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(infoLabel); + helpMouseListener.setHelpTopic(HELP_SIGNPIN); + helpKeyListener.setHelpTopic(HELP_SIGNPIN); - if (!renderHeaderPanel) { - infoHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(switchFocusDummyLabel) - .addComponent(helpLabel) - ; - infoVertical - .addComponent(switchFocusDummyLabel) - .addComponent(helpLabel) - ; - } + //TODO message panel - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(infoHorizontal) - .addComponent(msgLabel)); +// String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD); +// String msg = MessageFormat.format(msgPattern, new Object[] { +// pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() }); +// +// JLabel msgLabel = new JLabel(); +// msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD)); +// msgLabel.setText(msg); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(infoVertical) + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(infoLabel); + GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(infoLabel); + + if (!renderHeaderPanel) { + infoHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; + infoVertical + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; + } + + mainPanelLayout.setHorizontalGroup( + infoHorizontal); +// mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +// .addGroup(infoHorizontal) +// .addComponent(msgLabel)); + + mainPanelLayout.setVerticalGroup( + infoVertical); +// mainPanelLayout.createSequentialGroup() +// .addGroup(infoVertical) +// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +// .addComponent(msgLabel)); + + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup(); + GroupLayout.Group buttonVertical; + + JButton enterPINButton = new JButton(); + enterPINButton.setFont(enterPINButton.getFont().deriveFont(enterPINButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + enterPINButton.setText(getMessage(BUTTON_SIGN)); + enterPINButton.setActionCommand(enterPINCommand); + enterPINButton.addActionListener(enterPINListener); + + if (renderCancelButton) { + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + cancelButton.setText(getMessage(BUTTON_CANCEL)); + cancelButton.setActionCommand(cancelCommand); + cancelButton.addActionListener(cancelListener); + + buttonHorizontal + .addComponent(enterPINButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(msgLabel)); - - //no cancel button (cancel via pinpad) -// if (renderCancelButton) { -// JButton cancelButton = new JButton(); -// cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); -// cancelButton.setText(getMessage(BUTTON_CANCEL)); -// cancelButton.setActionCommand(cancelCommand); -// cancelButton.addActionListener(cancelListener); -// -// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); -// buttonPanel.setLayout(buttonPanelLayout); -// -// GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() -// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); -// GroupLayout.SequentialGroup buttonVertical = buttonPanelLayout.createSequentialGroup() -// .addComponent(cancelButton); -// -// buttonPanelLayout.setHorizontalGroup(buttonHorizontal); -// buttonPanelLayout.setVerticalGroup(buttonVertical); -// } + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + ; + buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(enterPINButton) + .addComponent(cancelButton) + ; + } else { + buttonHorizontal + .addComponent(enterPINButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + ; + buttonVertical = buttonPanelLayout.createSequentialGroup() + .addComponent(enterPINButton) + ; + } - contentPanel.validate(); - } - }); + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); + buttonPanelLayout.setVerticalGroup(buttonVertical); + + contentPanel.validate(); + } + }); + } + + @Override + public void correctionButtonPressed() { + log.debug("[" + Thread.currentThread().getName() + "] correction button pressed"); + + if (pinpadPINField != null) { + String maskedPIN = pinpadPINField.getText(); + pinpadPINField.setText(maskedPIN.substring(0, maskedPIN.length() - 1)); + } + } + + @Override + public void allKeysCleared() { + log.debug("[" + Thread.currentThread().getName() + "] all keys cleared"); + + if (pinpadPINField != null) { + pinpadPINField.setText(""); + } + } + + @Override + public void validKeyPressed() { + log.debug("[" + Thread.currentThread().getName() + "] valid key pressed"); + + if (pinpadPINField != null) { + pinpadPINField.setText(pinpadPINField.getText() + '*'); } + } @Override public void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener signListener, final String signCommand, final ActionListener cancelListener, final String cancelCommand, final ActionListener hashdataListener, final String hashdataCommand) { -// showSignaturePINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); -// } -// -// private void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener signListener, final String signCommand, final ActionListener cancelListener, final String cancelCommand, final ActionListener hashdataListener, final String hashdataCommand) { log.debug("scheduling signature-pin dialog"); @@ -1302,57 +1261,6 @@ public class BKUGUIImpl implements BKUGUIFacade { }); } -// @Override -// public void showWaitDialog(final String waitMessage) { -// -// log.debug("scheduling wait dialog"); -// -// SwingUtilities.invokeLater(new Runnable() { -// -// @Override -// public void run() { -// -// log.debug("show wait dialog"); -// -// mainPanel.removeAll(); -// buttonPanel.removeAll(); -// -// if (renderHeaderPanel) { -// titleLabel.setText(getMessage(TITLE_WAIT)); -// } -// -// helpListener.setHelpTopic(HELP_WAIT); -// -// JLabel waitMsgLabel = new JLabel(); -// waitMsgLabel.setFont(waitMsgLabel.getFont().deriveFont(waitMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); -// if (waitMessage != null) { -// waitMsgLabel.setText("" + waitMessage + ""); -// } else { -// waitMsgLabel.setText(getMessage(MESSAGE_WAIT)); -// } -// -// GroupLayout mainPanelLayout = new GroupLayout(mainPanel); -// mainPanel.setLayout(mainPanelLayout); -// -// GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() -// .addComponent(waitMsgLabel); -// GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) -// .addComponent(waitMsgLabel); -// -// if (!renderHeaderPanel) { -// messageHorizontal -// .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) -// .addComponent(helpLabel); -// messageVertical -// .addComponent(helpLabel); -// } -// mainPanelLayout.setHorizontalGroup(messageHorizontal); -// mainPanelLayout.setVerticalGroup(messageVertical); -// -// contentPanel.validate(); -// } -// }); -// } @Override public char[] getPin() { @@ -1395,7 +1303,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { try { - showMessageDialog(TITLE_HASHDATA, MESSAGE_HASHDATA_VIEWER); + showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_HASHDATA_VIEWER); showSecureViewer(dataToBeSigned.get(0), backListener, backCommand); } catch (FontProviderException ex) { log.error("failed to display secure viewer", ex); @@ -1411,7 +1319,7 @@ public class BKUGUIImpl implements BKUGUIFacade { } } else { log.debug("[" + Thread.currentThread().getName() + "] mime-type not supported by secure viewer, scheduling save dialog"); - showMessageDialog(TITLE_HASHDATA, MESSAGE_UNSUPPORTED_MIMETYPE); + showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_UNSUPPORTED_MIMETYPE); SecureViewerSaveDialog.showSaveDialog(dataToBeSigned.get(0), messages, backListener, backCommand); } } else { @@ -1421,28 +1329,7 @@ public class BKUGUIImpl implements BKUGUIFacade { /** * has to be called from event dispatcher thread - * @param hashDataText - * @param saveListener - * @param saveCommand */ -// private void showSecureViewer(HashDataInput dataToBeSigned) throws FontProviderException { -// -// log.debug("[" + Thread.currentThread().getName() + "] show secure viewer"); -// if (secureViewer == null) { -// secureViewer = new SecureViewerDialog(null, messages, -// fontProvider, helpMouseListener.getActionListener()); -// -// // workaround for [#439] -// // avoid AlwaysOnTop at least in applet, otherwise make secureViewer AlwaysOnTop since MOCCA Dialog (JFrame created in LocalSTALFactory) is always on top. -// Window window = SwingUtilities.getWindowAncestor(contentPane); -// if (window != null && window.isAlwaysOnTop()) { -// log.debug("make secureViewer alwaysOnTop"); -// secureViewer.setAlwaysOnTop(true); -// } -// } -// secureViewer.setContent(dataToBeSigned); -// log.trace("show secure viewer returned"); -// } private void showSecureViewer(HashDataInput dataToBeSigned, ActionListener closeListener, String closeCommand) throws FontProviderException { log.debug("[" + Thread.currentThread().getName() + "] show secure viewer"); @@ -1479,7 +1366,7 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonPanel.removeAll(); if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_HASHDATA)); + titleLabel.setText(getMessage(TITLE_SIGNATURE_DATA)); } helpMouseListener.setHelpTopic(HELP_HASHDATALIST); @@ -1613,7 +1500,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { try { - showMessageDialog(TITLE_HASHDATA, MESSAGE_HASHDATA_VIEWER); + showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_HASHDATA_VIEWER); showSecureViewer(selection, backToListListener, null); // SecureViewerDialog.showSecureViewer(selection, messages, fontProvider, helpMouseListener.getActionListener(), false); } catch (FontProviderException ex) { @@ -1625,7 +1512,7 @@ public class BKUGUIImpl implements BKUGUIFacade { }); } else { log.debug("[" + Thread.currentThread().getName() + "] mime-type not supported by secure viewer, scheduling save dialog"); - showMessageDialog(BKUGUIFacade.TITLE_HASHDATA, BKUGUIFacade.MESSAGE_UNSUPPORTED_MIMETYPE); + showMessageDialog(BKUGUIFacade.TITLE_SIGNATURE_DATA, BKUGUIFacade.MESSAGE_UNSUPPORTED_MIMETYPE); SecureViewerSaveDialog.showSaveDialog(selection, messages, backToListListener, null); } } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java index 96032dc1..52a3d5fe 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java @@ -1,19 +1,19 @@ /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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. -*/ + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.gui; import java.util.regex.Matcher; @@ -21,7 +21,6 @@ import java.util.regex.Pattern; import javax.swing.JButton; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; -import javax.swing.text.Document; import javax.swing.text.PlainDocument; /** @@ -31,16 +30,15 @@ import javax.swing.text.PlainDocument; class PINDocument extends PlainDocument { private static final long serialVersionUID = 1L; - protected Pattern pinPattern; protected int minLength; protected int maxLength; - protected JButton enterButton; - protected Document compareTo; - protected Document oldPin; public PINDocument(int minLength, int maxLength, String pattern, JButton enterButton) { + if (enterButton == null) { + throw new NullPointerException("OK button null"); + } if (pattern != null) { pinPattern = Pattern.compile(pattern); } else { @@ -51,73 +49,26 @@ class PINDocument extends PlainDocument { this.enterButton = enterButton; } - /** - * @param pinSpec - * @param enterButton - * @param compareTo - * enable enterButton if this pinDocument's pin equals to - * compareTo's pin. may be null - */ - public PINDocument(int minLength, int maxLength, String pattern, JButton enterButton, Document compareTo) { - this(minLength, maxLength, pattern, enterButton); - this.compareTo = compareTo; + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + if (maxLength < 0 || maxLength >= (getLength() + str.length())) { + boolean matches = true; + for (int i = 0; i < str.length(); i++) { + Matcher m = pinPattern.matcher(str.substring(i, i + 1)); + if (!m.matches()) { + matches = false; + } + } + if (matches) { + super.insertString(offs, str, a); + enterButton.setEnabled(getLength() >= minLength); + } + } } - /** - * @param pinSpec - * @param enterButton - * may be null - * @param compareTo - * enable enterButton if this pinDocument's pin equals to - * compareTo's pin. may be null - * @param oldPin - * enable enterButton if oldPin meets the pinSpec pin length - * requirements, may be null - */ - public PINDocument(int minLength, int maxLength, String pattern, - JButton enterButton, Document compareTo, Document oldPin) { - this(minLength, maxLength, pattern, enterButton); - this.compareTo = compareTo; - this.oldPin = oldPin; + @Override + public void remove(int offs, int len) throws BadLocationException { + super.remove(offs, len); + enterButton.setEnabled(getLength() >= minLength); } - - @Override - public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { - if (maxLength < 0 || maxLength >= (getLength() + str.length())) { - boolean matches = true; - for (int i = 0; i < str.length(); i++) { - Matcher m = pinPattern.matcher(str.substring(i, i + 1)); - if (!m.matches()) { - matches = false; - } - } - if (matches) { - super.insertString(offs, str, a); - } - } - if (enterButton != null) { - enterButton.setEnabled( - (oldPin == null || oldPin.getLength() >= minLength) && - getLength() >= minLength && - compare()); - } - } - - @Override - public void remove(int offs, int len) throws BadLocationException { - super.remove(offs, len); - if (enterButton != null) { - enterButton.setEnabled( - (oldPin == null || oldPin.getLength() >= minLength) && - getLength() >= minLength && - compare()); - } - } - - private boolean compare() throws BadLocationException { - if (compareTo == null) { - return true; - } - return compareTo.getText(0, compareTo.getLength()).equals(getText(0, getLength())); - } - } \ No newline at end of file +} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java index 7bae4673..7db70c46 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java @@ -17,7 +17,6 @@ package at.gv.egiz.bku.gui; import at.gv.egiz.bku.gui.viewer.FontProvider; -import at.gv.egiz.bku.gui.viewer.FontProviderException; import at.gv.egiz.bku.gui.viewer.SecureViewerSaveDialog; import at.gv.egiz.stal.HashDataInput; import java.awt.Container; @@ -25,7 +24,6 @@ import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; -import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; @@ -34,32 +32,26 @@ import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.io.BufferedOutputStream; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.Charset; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import java.util.ResourceBundle; import javax.swing.GroupLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JEditorPane; -import javax.swing.JFileChooser; import javax.swing.JLabel; -import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.LayoutStyle; -import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; import javax.swing.text.Document; import javax.swing.text.EditorKit; import javax.swing.text.StyledEditorKit; @@ -71,7 +63,7 @@ import org.apache.commons.logging.LogFactory; * * @author Clemens Orthacker */ -public class SecureViewerDialog extends JDialog implements ActionListener { +public class SecureViewerDialog extends JDialog { /** don't import BKUFonts in order not to load BKUFonts.jar * BKUApplet includes BKUFonts as runtime dependency only, the jar is copied to the applet dir in BKUOnline with dependency-plugin @@ -100,19 +92,6 @@ public class SecureViewerDialog extends JDialog implements ActionListener { * @param owner, dialog is positioned relative to its owner * (if null, at default location of native windowing system) */ -// public static void showDataToBeSigned(HashDataInput dataToBeSigned, -// ResourceBundle messages, -// ActionListener saveListener, String saveCommand, -// ActionListener helpListener) { -// -//// Frame ownerFrame = (owner != null) ? -//// JOptionPane.getFrameForComponent(owner) : -//// null; -// dialog = new SecureViewerDialog(null, messages, -// saveListener, saveCommand, helpListener); -// dialog.setContent(dataToBeSigned); -// dialog.setVisible(true); -// } public SecureViewerDialog(Frame owner, ResourceBundle messages, ActionListener closeListener, String closeCommand, FontProvider fontProvider, ActionListener helpListener) { @@ -125,6 +104,10 @@ public class SecureViewerDialog extends JDialog implements ActionListener { createViewerPanel(helpListener), createButtonPanel(closeListener, closeCommand)); + // also leave defaultWindowClosing HIDE_ON_CLOSE + this.addWindowListener(new WindowCloseListener(closeListener, closeCommand)); + this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + pack(); if (owner != null) { setLocationRelativeTo(owner); @@ -305,19 +288,11 @@ public class SecureViewerDialog extends JDialog implements ActionListener { JButton closeButton = new JButton(); closeButton.setText(messages.getString(BKUGUIFacade.BUTTON_CLOSE)); closeButton.setActionCommand(closeCommand); - closeButton.addActionListener(closeListener); - closeButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer"); - setVisible(false); - } - }); + closeButton.addActionListener(new CloseButtonListener(closeListener)); JButton saveButton = new JButton(); saveButton.setText(messages.getString(BKUGUIFacade.BUTTON_SAVE)); - saveButton.setActionCommand("save"); //TODO ensure unequal to closeCommand - saveButton.addActionListener(this); + saveButton.addActionListener(new SaveButtonListener()); int buttonSize = closeButton.getPreferredSize().width; if (saveButton.getPreferredSize().width > buttonSize) { @@ -336,39 +311,50 @@ public class SecureViewerDialog extends JDialog implements ActionListener { return buttonPanel; } - @Override - public void actionPerformed(ActionEvent e) { - if ("save".equals(e.getActionCommand())) { + public class WindowCloseListener extends WindowAdapter { + + ActionListener closeListener; + String closeCommand; + + public WindowCloseListener(ActionListener closeListener, String closeCommand) { + this.closeListener = closeListener; + this.closeCommand = closeCommand; + } + + @Override + public void windowClosing(WindowEvent e) { + log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer"); + setVisible(false); + if (closeListener != null) { + closeListener.actionPerformed(new ActionEvent(e.getSource(), e.getID(), closeCommand)); + } + } + } + + public class CloseButtonListener implements ActionListener { + + ActionListener closeListener; + + public CloseButtonListener(ActionListener closeListener) { + this.closeListener = closeListener; + } + + @Override + public void actionPerformed(ActionEvent e) { + log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer"); + setVisible(false); + if (closeListener != null) { + closeListener.actionPerformed(e); + } + } + } + + public class SaveButtonListener implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { log.trace("[" + Thread.currentThread().getName() + "] display secure viewer save dialog"); SecureViewerSaveDialog.showSaveDialog(content, messages, null, null); - log.trace("done secure viewer save"); - } else { - log.warn("unknown action command " + e.getActionCommand()); } } - - -// //TEST -// private static SecureViewerDialog secureViewer; -// public static void showSecureViewerXXX(HashDataInput dataToBeSigned, ResourceBundle messages, FontProvider fontProvider, ActionListener helpListener, boolean alwaysOnTop) throws FontProviderException { -// -//// ResourceBundle messages = ResourceBundle.getBundle(BKUGUIFacade.MESSAGES_BUNDLE, locale); -// -// log.debug("[" + Thread.currentThread().getName() + "] show secure viewer"); -// if (secureViewer == null) { -// secureViewer = new SecureViewerDialog(null, messages, -// fontProvider, helpListener); -// -// // workaround for [#439] -// // avoid AlwaysOnTop at least in applet, otherwise make secureViewer AlwaysOnTop since MOCCA Dialog (JFrame created in LocalSTALFactory) is always on top. -//// Window window = SwingUtilities.getWindowAncestor(contentPane); -//// if (window != null && window.isAlwaysOnTop()) { -//// log.debug("make secureViewer alwaysOnTop"); -// secureViewer.setAlwaysOnTop(alwaysOnTop); -//// } -// } -// secureViewer.setContent(dataToBeSigned); -// log.trace("show secure viewer returned"); -// } - } diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 3e483fc8..c09433de 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -16,15 +16,15 @@ title.welcome=Willkommen title.insertcard=Keine B\u00FCrgerkarte gefunden title.cardnotsupported=Die Karte wird nicht unterst\u00FCtzt -#title.cardpin={0} eingeben -title.cardpin=Karte wird gelesen +title.verify.pin=Karte wird gelesen title.sign=Signatur erstellen +title.verify.pinpad=PIN eingeben title.error=Fehler title.warning=Achtung title.entry.timeout=Zeit\u00FCberschreitung title.retry=Falsche PIN title.wait=Bitte warten -title.hashdata=Signaturdaten +title.signature.data=Signaturdaten windowtitle.save=Signaturdaten speichern windowtitle.error=Fehler windowtitle.savedir=Signaturdaten in Verzeichnis speichern @@ -38,7 +38,8 @@ wait=Bitte warten... cardnotsupported=Bitte die B\u00FCrgerkarte in den Kartenleser stecken insertcard=Bitte die B\u00FCrgerkarte in den Kartenleser stecken enterpin={0} eingeben -enterpin.pinpad={0} ({1} stellig) am Kartenleser eingeben +enterpin.pinpad=PIN am Kartenleser eingeben +enterpin.pinpad.direct={0} ({1} stellig) am Kartenleser eingeben hashdatalink=Signaturdaten anzeigen hashdatalink.tiny=Signaturdaten hashdatalink.focus=[Signaturdaten anzeigen] diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties index c553bcb5..4d86d21b 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties @@ -16,15 +16,15 @@ title.welcome=Welcome title.insertcard=No citizen card found title.cardnotsupported=This card is not supported -#title.cardpin=Enter {0} -title.cardpin=Reading card +title.verify.pin=Reading card title.sign=Create signature +title.verify.pinpad=Enter PIN title.error=Error title.warning=Warning title.entry.timeout=Timeout title.retry=Wrong PIN title.wait=Please wait -title.hashdata=Signature data +title.signature.data=Signature data windowtitle.save=Save signature data windowtitle.error=Error windowtitle.savedir=Save signature data to directory @@ -38,7 +38,8 @@ wait=Please wait... insertcard=Please insert your citizen card into the reader cardnotsupported=Please insert your citizen card into the reader enterpin=Enter {0} -enterpin.pinpad=Enter {0} ({1} digits) on card reader pinpad +enterpin.pinpad=Enter PIN on card reader pinpad +enterpin.pinpad.direct=Enter {0} ({1} digits) on card reader pinpad hashdatalink=Display signature data hashdatalink.tiny=signature data hashdatalink.focus=[Display signature data] diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index 6e345ee3..a2a84d6e 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -45,7 +45,7 @@ public class BKUGUIWorker implements Runnable { @Override public void run() { -// try { + try { final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Test-PIN", (byte) 0x81, null); final PINSpec cardPinSpec = new PINSpec(4, 4, "[0-9]", "Test-PIN", (byte) 0x01, null); @@ -155,7 +155,10 @@ public class BKUGUIWorker implements Runnable { // // gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); - gui.showPinpadSignaturePINDialog(signPinSpec, -1, hashdataListener, "hashdata"); + gui.showSignatureDataDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); + Thread.sleep(2000); + + gui.showEnterPINDirect(signPinSpec, -1); // // Thread.sleep(4000); // @@ -189,8 +192,8 @@ public class BKUGUIWorker implements Runnable { // gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save"); // Thread.sleep(2000); -// } catch (InterruptedException ex) { -// ex.printStackTrace(); -// } + } catch (InterruptedException ex) { + ex.printStackTrace(); + } } } diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ComparePinDocument.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ComparePinDocument.java new file mode 100644 index 00000000..623f6fad --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ComparePinDocument.java @@ -0,0 +1,102 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.gui; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JButton; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.PlainDocument; + +/** + * Checks if the pin confirmation (compareTo) corresponds to this pin. + * Additionally, checks if currentPIN (optional) meets the requirements before enabling the OK button. + * @author clemens + */ +class ComparePinDocument extends PlainDocument { + + private static final long serialVersionUID = 1L; + protected Pattern pinPattern; + protected int minLength; + protected int maxLength; + protected JButton enterButton; + protected Document compareTo; + protected Document currentPIN; + + /** + * Constructor without compareTo Document parameter (allow null and set later to avoid cyclic dependencies) + */ + public ComparePinDocument(int minLength, int maxLength, String pattern, JButton enterButton) { + if (enterButton == null) { + throw new NullPointerException("OK button null"); + } + if (pattern != null) { + pinPattern = Pattern.compile(pattern); + } else { + pinPattern = Pattern.compile("."); + } + this.minLength = minLength; + this.maxLength = maxLength; + this.enterButton = enterButton; + } + + /** + * @param compareTo should not be null (allow null and set later to avoid cyclic dependencies) + */ + public ComparePinDocument(int minLength, int maxLength, String pattern, + JButton enterButton, Document compareTo) { + this(minLength, maxLength, pattern, enterButton); + this.compareTo = compareTo; + } + + public ComparePinDocument(int minLength, int maxLength, String pattern, + JButton enterButton, Document compareTo, Document currentPIN) { + this(minLength, maxLength, pattern, enterButton, compareTo); + this.currentPIN = currentPIN; + } + + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + if (maxLength < 0 || maxLength >= (getLength() + str.length())) { + boolean matches = true; + for (int i = 0; i < str.length(); i++) { + Matcher m = pinPattern.matcher(str.substring(i, i + 1)); + if (!m.matches()) { + matches = false; + } + } + if (matches) { + super.insertString(offs, str, a); + enterButton.setEnabled( + getLength() >= minLength + && (currentPIN == null || currentPIN.getLength() >= minLength) + && compareTo.getText(0, compareTo.getLength()).equals(getText(0, getLength()))); + } + } + } + + @Override + public void remove(int offs, int len) throws BadLocationException { + super.remove(offs, len); + enterButton.setEnabled( + getLength() >= minLength + && (currentPIN == null || currentPIN.getLength() >= minLength) + && compareTo.getText(0, compareTo.getLength()).equals(getText(0, getLength()))); + } +} diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ExtendedPinDocument.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ExtendedPinDocument.java new file mode 100644 index 00000000..3a0d7a66 --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ExtendedPinDocument.java @@ -0,0 +1,108 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.gui; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JButton; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.PlainDocument; + +/** + * This PINDocument also checks if the additional (optional) pinDocuments also meet the requirements + * to enable the OK button. + * Checks if (optional) newPIN and confirmPIN correspond + * + * @author clemens + */ +class ExtendedPinDocument extends PlainDocument { + + private static final long serialVersionUID = 1L; + protected Pattern pinPattern; + protected int minLength; + protected int maxLength; + protected JButton enterButton; + protected Document newPIN; + protected Document confirmPIN; + + public ExtendedPinDocument(int minLength, int maxLength, String pattern, JButton enterButton) { + if (enterButton == null) { + throw new NullPointerException("OK Button null"); + } + if (pattern != null) { + pinPattern = Pattern.compile(pattern); + } else { + pinPattern = Pattern.compile("."); + } + this.minLength = minLength; + this.maxLength = maxLength; + this.enterButton = enterButton; + } + + /** + * @param pinSpec + * @param enterButton + * @param newPIN, confirmPIN + */ + public ExtendedPinDocument(int minLength, int maxLength, String pattern, JButton enterButton, Document newPIN, Document confirmPIN) { + this(minLength, maxLength, pattern, enterButton); + this.newPIN = newPIN; + this.confirmPIN = confirmPIN; + } + + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + if (maxLength < 0 || maxLength >= (getLength() + str.length())) { + boolean matches = true; + for (int i = 0; i < str.length(); i++) { + Matcher m = pinPattern.matcher(str.substring(i, i + 1)); + if (!m.matches()) { + matches = false; + } + } + if (matches) { + super.insertString(offs, str, a); + enterButton.setEnabled( + getLength() >= minLength + && (newPIN == null || newPIN.getLength() >= minLength) + && (confirmPIN == null || compare())); + } + } + } + + @Override + public void remove(int offs, int len) throws BadLocationException { + super.remove(offs, len); + enterButton.setEnabled( + getLength() >= minLength + && (newPIN == null || newPIN.getLength() >= minLength) + && (confirmPIN == null || compare())); + } + + /** + * assume confirmPIN != null + * @return + */ + private boolean compare() throws BadLocationException { + if (newPIN != null) { + return confirmPIN.getText(0, confirmPIN.getLength()).equals(newPIN.getText(0, newPIN.getLength())); + } + return false; + } +} diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java index 5bbed096..4dcc388f 100644 --- a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -239,23 +239,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac } @Override - public void showPINDialog(DIALOG type, PINSpec pinSpec, - ActionListener okListener, String okCommand, - ActionListener cancelListener, String cancelCommand) { - showPINDialog(type, pinSpec, -1, false, - okListener, okCommand, cancelListener, cancelCommand); - } - - @Override - public void showPINDialog(DIALOG type, PINSpec pinSpec, int retries, - ActionListener okListener, String okCommand, - ActionListener cancelListener, String cancelCommand) { - showPINDialog(type, pinSpec, retries, false, - okListener, okCommand, cancelListener, cancelCommand); - } - - @Override - public void showPinpadPINDialog(DIALOG type, PINSpec pinSpec, int retries) { + public void showModifyPINDirect(DIALOG type, PINSpec pinSpec, int retries) { String title, msg; Object[] params; if (retries < 0) { @@ -269,19 +253,19 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac if (type == DIALOG.CHANGE) { log.debug("show change pin dialog"); title = TITLE_CHANGE_PIN; - msg = MESSAGE_CHANGEPIN_PINPAD; + msg = MESSAGE_CHANGE_PINPAD_DIREKT; } else if (type == DIALOG.ACTIVATE) { log.debug("show activate pin dialog"); title = TITLE_ACTIVATE_PIN; - msg = MESSAGE_ENTERPIN_PINPAD; + msg = MESSAGE_ACTIVATE_PINPAD_DIREKT; } else if (type == DIALOG.VERIFY) { log.debug("show verify pin dialog"); - title = TITLE_VERIFY_PIN; - msg = MESSAGE_ENTERPIN_PINPAD; + title = TITLE_VERIFY_PINPAD; + msg = MESSAGE_ENTERPIN_PINPAD_DIRECT; } else { log.debug("show unblock pin dialog"); title = TITLE_UNBLOCK_PIN; - msg = MESSAGE_ENTERPIN_PINPAD; + msg = MESSAGE_UNBLOCK_PINPAD_DIREKT; } } else { @@ -294,6 +278,15 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac showMessageDialog(title, msg, params); } + @Override + public void showPINDialog(DIALOG type, PINSpec pinSpec, int retries, + ActionListener okListener, String okCommand, + ActionListener cancelListener, String cancelCommand) { + showPINDialog(type, pinSpec, retries, false, + okListener, okCommand, cancelListener, cancelCommand); + } + + private void showPINDialog(final DIALOG type, final PINSpec pinSpec, final int retries, final boolean pinpad, final ActionListener okListener, final String okCommand, @@ -322,7 +315,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac } else if (type == DIALOG.VERIFY) { log.debug("show verify pin dialog"); TITLE = TITLE_VERIFY_PIN; - MESSAGE_MGMT = MESSAGE_VERIFY_PIN; + MESSAGE_MGMT = MESSAGE_ENTERPIN; } else { log.debug("show unblock pin dialog"); TITLE = TITLE_UNBLOCK_PIN; @@ -393,7 +386,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac if (pinpad) { JLabel pinpadLabel = new JLabel(); pinpadLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); - String pinpadPattern = getMessage(MESSAGE_VERIFYPIN_PINPAD); + String pinpadPattern = getMessage(MESSAGE_ENTERPIN_PINPAD); pinpadLabel.setText(MessageFormat.format(pinpadPattern, new Object[] { pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() })); @@ -403,7 +396,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac .addComponent(pinpadLabel); } else { - JButton okButton = new JButton(); + final JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~Font.BOLD)); okButton.setText(getMessage(BUTTON_OK)); okButton.setEnabled(pinSpec.getMinLength() <= 0); @@ -414,7 +407,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac JLabel repeatPinLabel = null; JLabel pinLabel = new JLabel(); pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~Font.BOLD)); - String pinLabelPattern = (type == DIALOG.CHANGE) ? getMessage(LABEL_NEW_PIN) : getMessage(LABEL_PIN); + String pinLabelPattern = (type == DIALOG.CHANGE || type == DIALOG.UNBLOCK) ? getMessage(LABEL_NEW_PIN) : getMessage(LABEL_PIN); pinLabel.setText(MessageFormat.format(pinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); final JPasswordField repeatPinField = new JPasswordField(); @@ -436,8 +429,6 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac }); if (type != DIALOG.VERIFY) { - pinField.setDocument( - new PINDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), null)); repeatPinLabel = new JLabel(); repeatPinLabel.setFont(pinLabel.getFont()); String repeatPinLabelPattern = getMessage(LABEL_REPEAT_PIN); @@ -449,22 +440,20 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac @Override public void actionPerformed(ActionEvent e) { - if (pinField.getPassword().length >= pinSpec.getMinLength()) { + if (okButton.isEnabled()) { okListener.actionPerformed(e); } } }); - if (type == DIALOG.CHANGE) { + if (type == DIALOG.CHANGE || type == DIALOG.UNBLOCK) { oldPinLabel = new JLabel(); oldPinLabel.setFont(oldPinLabel.getFont().deriveFont(oldPinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - String oldPinLabelPattern = getMessage(LABEL_OLD_PIN); + String oldPinLabelPattern = getMessage((type == DIALOG.CHANGE) ? LABEL_OLD_PIN : LABEL_PUK); oldPinLabel.setText(MessageFormat.format(oldPinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); oldPinField = new JPasswordField(); oldPinField.setText(""); - oldPinField.setDocument( - new PINDocument(pinSpec.getMinLength(), pinSpec.getMaxLength(), pinSpec.getRexepPattern(), null)); oldPinField.setActionCommand(okCommand); oldPinField.addActionListener(new ActionListener() { @@ -476,16 +465,45 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac } }); - repeatPinField.setDocument( - new PINDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), - okButton, pinField.getDocument(), oldPinField.getDocument())); + ExtendedPinDocument oldPinDocument = + new ExtendedPinDocument(pinSpec.getMinLength(), pinSpec.getMaxLength(), + pinSpec.getRexepPattern(), okButton); + ComparePinDocument newPinDocument = + new ComparePinDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), + okButton); + ComparePinDocument confirmPinDocument = + new ComparePinDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), + okButton); + + oldPinDocument.newPIN = newPinDocument; + oldPinDocument.confirmPIN = confirmPinDocument; + + newPinDocument.compareTo = confirmPinDocument; + newPinDocument.currentPIN = oldPinDocument; + confirmPinDocument.compareTo = newPinDocument; + confirmPinDocument.currentPIN = oldPinDocument; + + oldPinField.setDocument(oldPinDocument); + pinField.setDocument(newPinDocument); + repeatPinField.setDocument(confirmPinDocument); + } else { // else -> ACTIVATE (not verify, not change) - repeatPinField.setDocument( - new PINDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), - okButton, pinField.getDocument())); + ComparePinDocument newPinDocument = + new ComparePinDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), + okButton); + ComparePinDocument confirmPinDocument = + new ComparePinDocument(pinSpec.getRecMinLength(), pinSpec.getRecMaxLength(), pinSpec.getRexepPattern(), + okButton); + + newPinDocument.compareTo = confirmPinDocument; + confirmPinDocument.compareTo = newPinDocument; + + pinField.setDocument(newPinDocument); + repeatPinField.setDocument(confirmPinDocument); } } else { + // VERIFY pinField.setDocument( new PINDocument(pinSpec.getMinLength(), pinSpec.getMaxLength(), pinSpec.getRexepPattern(), okButton)); } @@ -534,7 +552,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac // } else { - if (type == DIALOG.CHANGE) { + if (type == DIALOG.CHANGE || type == DIALOG.UNBLOCK) { pinHorizontal .addGroup(mainPanelLayout.createSequentialGroup() .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) @@ -675,4 +693,69 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac return bs; } + @Override + public void showEnterCurrentPIN(DIALOG type, PINSpec pinSpec, int retries) { + String title, message; +// Object[] params = null; + + if (type == PINManagementGUIFacade.DIALOG.VERIFY) { + title = PINManagementGUIFacade.TITLE_VERIFY_PINPAD; + message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; +// params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; + } else if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { + title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; + message = PINManagementGUIFacade.MESSAGE_ACTIVATE_PINPAD_CURRENT; +// params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; + } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { + title = PINManagementGUIFacade.TITLE_CHANGE_PIN; + message = PINManagementGUIFacade.MESSAGE_CHANGE_PINPAD_CURRENT; +// params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; + } else { //if (type == DIALOG.UNBLOCK) { + title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; + message = PINManagementGUIFacade.MESSAGE_UNBLOCK_PINPAD_CURRENT; +// params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; + } + showEnterPIN(pinSpec, retries, title, message, null); + } + + @Override + public void showEnterNewPIN(DIALOG type, PINSpec pinSpec) { + String title, message; + if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { + title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; + message = PINManagementGUIFacade.MESSAGE_ACTIVATE_PINPAD_NEW; + } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { + title = PINManagementGUIFacade.TITLE_CHANGE_PIN; + message = PINManagementGUIFacade.MESSAGE_CHANGE_PINPAD_NEW; + } else if (type == DIALOG.UNBLOCK) { + title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; + message = PINManagementGUIFacade.MESSAGE_UNBLOCK_PINPAD_NEW; + } else { + log.error("enterNewPIN not supported for dialog type " + type); + showErrorDialog(ERR_UNKNOWN, null); + return; + } + showEnterPIN(pinSpec, -1, title, message, null); + } + + @Override + public void showConfirmNewPIN(DIALOG type, PINSpec pinSpec) { + String title, message; + if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { + title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; + message = PINManagementGUIFacade.MESSAGE_ACTIVATE_PINPAD_CONFIRM; + } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { + title = PINManagementGUIFacade.TITLE_CHANGE_PIN; + message = PINManagementGUIFacade.MESSAGE_CHANGE_PINPAD_CONFIRM; + } else if (type == DIALOG.UNBLOCK) { + title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; + message = PINManagementGUIFacade.MESSAGE_UNBLOCK_PINPAD_CONFIRM; + } else { + log.error("enterNewPIN not supported for dialog type " + type); + showErrorDialog(ERR_UNKNOWN, null); + return; + } + showEnterPIN(pinSpec, -1, title, message, null); + } + } diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java index f99bcfd1..46ae18b9 100644 --- a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -32,26 +32,39 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String TITLE_PINMGMT = "title.pin.mgmt"; public static final String TITLE_ACTIVATE_PIN = "title.activate.pin"; public static final String TITLE_CHANGE_PIN = "title.change.pin"; - public static final String TITLE_VERIFY_PIN = "title.verify.pin"; +// public static final String TITLE_VERIFY_PIN = "title.verify.pin"; public static final String TITLE_UNBLOCK_PIN = "title.unblock.pin"; public static final String TITLE_ACTIVATE_SUCCESS = "title.activate.success"; + public static final String TITLE_UNBLOCK_SUCCESS = "title.unblock.success"; public static final String TITLE_CHANGE_SUCCESS = "title.change.success"; // removed message.* prefix to reuse keys as help keys public static final String MESSAGE_ACTIVATE_SUCCESS = "activate.success"; public static final String MESSAGE_CHANGE_SUCCESS = "change.success"; + public static final String MESSAGE_UNBLOCK_SUCCESS = "unblock.success"; public static final String MESSAGE_PINMGMT = "pin.mgmt"; // public static final String MESSAGE_PINPAD = "pinpad"; + public static final String MESSAGE_ACTIVATE_PIN = "activate.pin"; public static final String MESSAGE_CHANGE_PIN = "change.pin"; - public static final String MESSAGE_VERIFY_PIN = "verify.pin"; public static final String MESSAGE_UNBLOCK_PIN = "unblock.pin"; - public static final String MESSAGE_ACTIVATEPIN_PINPAD = "activate.pinpad"; - public static final String MESSAGE_CHANGEPIN_PINPAD = "change.pinpad"; - public static final String MESSAGE_VERIFYPIN_PINPAD = "verify.pinpad"; - public static final String MESSAGE_UNBLOCKPIN_PINPAD = "unblock.pinpad"; + + public static final String MESSAGE_ACTIVATE_PINPAD_CURRENT = "activate.pinpad.current"; + public static final String MESSAGE_CHANGE_PINPAD_CURRENT = "change.pinpad.current"; + public static final String MESSAGE_UNBLOCK_PINPAD_CURRENT = "unblock.pinpad.current"; + public static final String MESSAGE_ACTIVATE_PINPAD_NEW = "activate.pinpad.new"; + public static final String MESSAGE_CHANGE_PINPAD_NEW = "change.pinpad.new"; + public static final String MESSAGE_UNBLOCK_PINPAD_NEW = "unblock.pinpad.new"; + public static final String MESSAGE_ACTIVATE_PINPAD_CONFIRM = "activate.pinpad.confirm"; + public static final String MESSAGE_CHANGE_PINPAD_CONFIRM = "change.pinpad.confirm"; + public static final String MESSAGE_UNBLOCK_PINPAD_CONFIRM = "unblock.pinpad.confirm"; + + public static final String MESSAGE_ACTIVATE_PINPAD_DIREKT = "activate.pinpad.direct"; + public static final String MESSAGE_CHANGE_PINPAD_DIREKT = "change.pinpad.direct"; + public static final String MESSAGE_UNBLOCK_PINPAD_DIREKT = "unblock.pinpad.direct"; public static final String LABEL_OLD_PIN = "label.old.pin"; + public static final String LABEL_PUK = "label.puk"; public static final String LABEL_NEW_PIN = "label.new.pin"; public static final String LABEL_REPEAT_PIN = "label.repeat.pin"; @@ -81,35 +94,34 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED, UNKNOWN }; public enum DIALOG { VERIFY, ACTIVATE, CHANGE, UNBLOCK }; + /** + * list pins + */ public void showPINManagementDialog(Map pins, ActionListener activateListener, String activateCmd, String changeCmd, String unblockCmd, String verifyCmd, ActionListener cancelListener, String cancelCmd); - public void showPINDialog(DIALOG type, PINSpec pin, + /** + * "software" pin-entry dialog (activate, change, unblock, verify) + */ + public void showPINDialog(DIALOG type, PINSpec pinSpec, int retries, ActionListener okListener, String okCmd, ActionListener cancelListener, String cancelCmd); - public void showPINDialog(DIALOG type, PINSpec pin, int retries, - ActionListener okListener, String okCmd, - ActionListener cancelListener, String cancelCmd); + /** + * direct pinpad pin-entry dialog + */ + public void showModifyPINDirect(DIALOG type, PINSpec pinSpec, int retries); + + /** + * start/finish pinpad pin-entry dialog + */ + public void showEnterCurrentPIN(DIALOG type, PINSpec pinSpec, int retries); + + public void showEnterNewPIN(DIALOG type, PINSpec pinSpec); + + public void showConfirmNewPIN(DIALOG type, PINSpec pinSpec); - public void showPinpadPINDialog(DIALOG type, PINSpec pin, int retries); - -// public void showActivatePINDialog(PINSpec pin, -// ActionListener okListener, String okCmd, -// ActionListener cancelListener, String cancelCmd); -// -// public void showChangePINDialog(PINSpec pin, -// ActionListener okListener, String okCmd, -// ActionListener cancelListener, String cancelCmd); -// -// public void showUnblockPINDialog(PINSpec pin, -// ActionListener okListener, String okCmd, -// ActionListener cancelListener, String cancelCmd); -// -// public void showVerifyPINDialog(PINSpec pin, -// ActionListener okListener, String okCmd, -// ActionListener cancelListener, String cancelCmd); public char[] getOldPin(); diff --git a/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties index 977d6e3a..5ef3edee 100644 --- a/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -15,30 +15,44 @@ title.activation=Aktivierung title.pin.mgmt=PIN Verwaltung -title.activate.pin=PIN Aktivieren -title.change.pin=PIN \u00C4ndern -title.unblock.pin=PIN Entsperren -title.verify.pin=PIN Eingeben +title.activate.pin=PIN aktivieren +title.change.pin=PIN \u00E4ndern +title.unblock.pin=PIN entsperren +#title.verify.pin=PIN Eingeben title.activate.success=Erfolg title.change.success=Erfolg +title.unblock.success=Erfolg # removed message.* prefix to reuse keys as help keys pin.mgmt=Die Karte verf\u00FCgt \u00FCber {0} PINs +# software pin-entry messages activate.pin={0} eingeben und best\u00E4tigen change.pin={0} eingeben und best\u00E4tigen unblock.pin=PUK zu {0} eingeben -verify.pin={0} eingeben -verify.pinpad={0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen). -activate.pinpad={0} ({1} stellig) am Kartenleser eingeben und wiederholen (jeweils best\u00E4tigen). -change.pinpad=Alte {0} ({1} stellig) am Kartenleser eingeben, danach neue {0} eingeben und wiederholen (jeweils best\u00E4tigen). -unblock.pinpad={0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen). -activate.success={0} wurde erfolgreich aktiviert. -change.success={0} wurde erfolgreich ge\u00E4ndert. +# start/finish pin-entry messages +activate.pinpad.current=Transport-PIN am Kartenleser eingeben +activate.pinpad.new=Neue PIN am Kartenleser eingeben +activate.pinpad.confirm=Neue PIN am Kartenleser best\u00E4tigen +change.pinpad.current=Alte PIN am Kartenleser eingeben +change.pinpad.new=Neue PIN am Kartenleser eingeben +change.pinpad.confirm=Neue PIN am Kartenleser best\u00E4tigen +unblock.pinpad.current=PUK am Kartenleser eingeben +unblock.pinpad.new=Neue PIN am Kartenleser eingeben +unblock.pinpad.confirm=Neue PIN am Kartenleser best\u00E4tigen +# direct pin-entry messages +activate.pinpad.direct={0} ({1} stellig) am Kartenleser eingeben und wiederholen (jeweils best\u00E4tigen). +change.pinpad.direct=Alte {0} ({1} stellig) am Kartenleser eingeben, danach neue {0} eingeben und wiederholen (jeweils best\u00E4tigen). +unblock.pinpad.direct={0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen). +# response messages +activate.success={0} wurde erfolgreich aktiviert +change.success={0} wurde erfolgreich ge\u00E4ndert +unblock.success={0} wurde erfolgreich entsperrt label.activation=e-card Aktivierungsprozess label.activation.step=Schritt {0} label.activation.idle=Warte auf Server... label.old.pin=Alte {0}: +label.puk={0} PUK: label.new.pin=Neue {0}: label.repeat.pin=Best\u00E4tigung: diff --git a/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties index 7f01971b..87e3f181 100644 --- a/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -16,29 +16,43 @@ title.activation=Activation title.pin.mgmt=PIN Management title.activate.pin=Activate PIN -title.verify.pin=Enter PIN +#title.verify.pin=Enter PIN title.change.pin=Change PIN title.unblock.pin=Unblock PIN title.activate.success=Success title.change.success=Success +title.unblock.success=Success # removed message.* prefix to reuse keys as help keys -pin.mgmt=The smartcard has {0} PINs -activate.pin=Enter and confirm {0} -change.pin=Enter and confirm {0} -unblock.pin=Enter PUK for {0} -verify.pin=Enter {0} -verify.pinpad=Enter {0} ({1} digits) on cardreader (and confirm). -activate.pinpad=Enter {0} ({1} digits) on cardreader and repeat (confirm in each case). -change.pinpad=Enter old {0} ({1} digits) on cardreader, then enter new {0} and repeat (confirm in each case). -unblock.pinpad=Enter {0} ({1} digits) on cardreader (and confirm). +pin.mgmt={0} PINs available +# software pin-entry messages +activate.pin=Enter and confirm {0} +change.pin=Enter and confirm {0} +unblock.pin=Enter PUK for {0} +# start/finish pin-entry messages +activate.pinpad.current=Enter transport-PIN on cardreader +activate.pinpad.new=Enter new PIN on cardreader +activate.pinpad.confirm=Confirm new PIN on cardreader +change.pinpad.current=Enter old PIN on cardreader +change.pinpad.new=Enter new PIN on cardreader +change.pinpad.confirm=Confirm new PIN on cardreader +unblock.pinpad.current=Enter PUK on cardreader +unblock.pinpad.new=Enter new PIN on cardreader +unblock.pinpad.confirm=Confirm new PIN on cardreader +# direct pin-entry messages +activate.pinpad.direct=Enter {0} ({1} digits) on cardreader and repeat (confirm in each case) +change.pinpad.direct=Enter old {0} ({1} digits) on cardreader, then enter new {0} and repeat (confirm in each case) +unblock.pinpad.direct=Enter {0} ({1} digits) on cardreader, then enter new {0} and repeat (confirm in each case) +# response messages activate.success={0} successfully activated change.success={0} successfully changed +unblock.success={0} successfully unblocked label.activation=e-card activation process label.activation.step=Step {0} label.activation.idle=Wait for server... label.old.pin=Old {0}: +label.puk={0} PUK: label.new.pin=New {0}: label.repeat.pin=Confirmation: diff --git a/BKUOnline/src/main/resources/log4j.properties b/BKUOnline/src/main/resources/log4j.properties index 3eab8604..40133c83 100644 --- a/BKUOnline/src/main/resources/log4j.properties +++ b/BKUOnline/src/main/resources/log4j.properties @@ -15,7 +15,7 @@ #log4j.rootLogger=DEBUG, STDOUT, file -log4j.rootLogger=INFO, file +log4j.rootLogger=TRACE, file #log4j.logger.at.gv = INFO diff --git a/BKUOnline/src/main/webapp/META-INF/context.xml b/BKUOnline/src/main/webapp/META-INF/context.xml index 2a2da79e..f38215a1 100644 --- a/BKUOnline/src/main/webapp/META-INF/context.xml +++ b/BKUOnline/src/main/webapp/META-INF/context.xml @@ -16,4 +16,4 @@ limitations under the License. --> - + diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java index 1ed5a177..b8cdb208 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -16,6 +16,8 @@ */ package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -79,10 +81,16 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC public static final byte KID_PIN_SIG = (byte) 0x81; + public static final byte KID_PUK_SIG = (byte) 0x83; + public static final byte KID_PIN_DEC = (byte) 0x81; + public static final byte KID_PUK_DEC = (byte) 0x82; + public static final byte KID_PIN_INF = (byte) 0x83; + public static final byte KID_PUK_INF = (byte) 0x84; + public static final byte[] DST_SIG = new byte[] { (byte) 0x84, (byte) 0x01, // tag // , // length @@ -217,7 +225,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC @Override @Exclusive - public byte[] getInfobox(String infobox, PINProvider provider, String domainId) + public byte[] getInfobox(String infobox, PINGUI provider, String domainId) throws SignatureCardException, InterruptedException { if ("IdentityLink".equals(infobox)) { @@ -233,7 +241,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC } - protected byte[] getIdentityLinkV1(PINProvider provider, String domainId) + protected byte[] getIdentityLinkV1(PINGUI provider, String domainId) throws SignatureCardException, InterruptedException { try { @@ -262,7 +270,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC } - protected byte[] getIdentityLinkV2(PINProvider provider, String domainId) + protected byte[] getIdentityLinkV2(PINGUI provider, String domainId) throws SignatureCardException, InterruptedException { try { @@ -388,7 +396,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC @Override @Exclusive public byte[] createSignature(InputStream input, KeyboxName keyboxName, - PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { + PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException { ByteArrayOutputStream dst = new ByteArrayOutputStream(); // key ID @@ -487,7 +495,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC * @see at.gv.egiz.smcc.AbstractSignatureCard#verifyPIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider) */ @Override - public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + public void verifyPIN(PINSpec pinSpec, PINGUI pinProvider) throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { @@ -509,7 +517,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC * @see at.gv.egiz.smcc.AbstractSignatureCard#changePIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.ChangePINProvider) */ @Override - public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) + public void changePIN(PINSpec pinSpec, ModifyPINGUI pinProvider) throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { @@ -528,7 +536,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC } @Override - public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) + public void activatePIN(PINSpec pinSpec, ModifyPINGUI pinGUI) throws CancelledException, SignatureCardException, CancelledException, TimeoutException, InterruptedException { log.error("ACTIVATE PIN not supported by ACOS"); @@ -536,7 +544,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC } @Override - public void unblockPIN(PINSpec pinSpec, PINProvider pinProvider) + public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pinGUI) throws CancelledException, SignatureCardException, InterruptedException { throw new SignatureCardException("Unblock PIN not supported."); } @@ -570,10 +578,8 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC // PROTECTED METHODS (assume exclusive card access) //////////////////////////////////////////////////////////////////////// - protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINProvider provider) - throws InterruptedException, LockedException, NotActivatedException, - TimeoutException, PINFormatException, PINOperationAbortedException, - SignatureCardException, CardException { + protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINGUI provider) + throws InterruptedException, CardException, SignatureCardException { int retries = -1; do { @@ -581,10 +587,8 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC } while (retries > 0); } - protected void changePINLoop(CardChannel channel, PINSpec spec, ChangePINProvider provider) - throws InterruptedException, LockedException, NotActivatedException, - TimeoutException, PINFormatException, PINOperationAbortedException, - SignatureCardException, CardException { + protected void changePINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider) + throws InterruptedException, CardException, SignatureCardException { int retries = -1; do { @@ -593,7 +597,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC } protected int verifyPIN(CardChannel channel, PINSpec pinSpec, - PINProvider provider, int retries) throws InterruptedException, CardException, SignatureCardException { + PINGUI provider, int retries) throws InterruptedException, CardException, SignatureCardException { VerifyAPDUSpec apduSpec = new VerifyAPDUSpec( new byte[] { @@ -602,7 +606,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }, 0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8); - ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); + ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries); if (resp.getSW() == 0x9000) { return -1; @@ -625,7 +629,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC } protected int changePIN(CardChannel channel, PINSpec pinSpec, - ChangePINProvider pinProvider, int retries) throws CancelledException, InterruptedException, CardException, SignatureCardException { + ModifyPINGUI pinProvider, int retries) throws CancelledException, InterruptedException, CardException, SignatureCardException { ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec( new byte[] { @@ -639,7 +643,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC - ResponseAPDU resp = reader.modify(channel, apduSpec, pinSpec, pinProvider, retries); + ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinSpec, retries); if (resp.getSW() == 0x9000) { return -1; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java index 54b4c7fe..fcb94fc6 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -16,6 +16,8 @@ */ package at.gv.egiz.smcc; +import at.gv.egiz.smcc.reader.CardReader; +import at.gv.egiz.smcc.reader.ReaderFactory; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -29,9 +31,6 @@ import javax.smartcardio.CardTerminal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.ccid.ReaderFactory; - public abstract class AbstractSignatureCard implements SignatureCard { private static Log log = LogFactory.getLog(AbstractSignatureCard.class); @@ -45,7 +44,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { private Card card_; - protected CCID reader; + protected CardReader reader; protected AbstractSignatureCard(String resourceBundleName) { this.resourceBundleName = resourceBundleName; @@ -68,7 +67,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { @Override public void init(Card card, CardTerminal cardTerminal) { this.card_ = card; - this.reader = ReaderFactory.getInstance().getReader(card, cardTerminal); + this.reader = ReaderFactory.getReader(card, cardTerminal); } @Override @@ -80,11 +79,6 @@ public abstract class AbstractSignatureCard implements SignatureCard { return new LogCardChannel(card_.getBasicChannel()); } - @Override - public CCID getReader() { - return reader; - } - @Override public void setLocale(Locale locale) { if (locale == null) { diff --git a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java index e02a55d4..41358bb5 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java @@ -18,6 +18,7 @@ package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.PINGUI; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; @@ -110,7 +111,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard { @Override @Exclusive - public byte[] getInfobox(String infobox, PINProvider provider, String domainId) + public byte[] getInfobox(String infobox, PINGUI provider, String domainId) throws SignatureCardException, InterruptedException { throw new IllegalArgumentException("Infobox '" + infobox @@ -120,7 +121,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard { @Override @Exclusive public byte[] createSignature(InputStream input, KeyboxName keyboxName, - PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { + PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException { if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { throw new SignatureCardException("Card does not support key " + keyboxName + "."); @@ -176,7 +177,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard { } protected void verifyPINLoop(CardChannel channel, PINSpec spec, - PINProvider provider) throws LockedException, NotActivatedException, + PINGUI provider) throws LockedException, NotActivatedException, SignatureCardException, InterruptedException, CardException { int retries = -1; //verifyPIN(channel, spec, null, -1); @@ -186,7 +187,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard { } protected int verifyPIN(CardChannel channel, PINSpec pinSpec, - PINProvider provider, int retries) throws SignatureCardException, + PINGUI provider, int retries) throws SignatureCardException, LockedException, NotActivatedException, InterruptedException, CardException { @@ -197,7 +198,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard { (byte) 0xff, (byte) 0xff, (byte) 0xff }, 1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); - ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); + ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries); if (resp.getSW() == 0x9000) { return -1; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java deleted file mode 100644 index 41010551..00000000 --- a/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.smcc; - -/** - * - * @author Clemens Orthacker - */ -public interface ChangePINProvider extends PINProvider { - - /** - * - * @param spec - * @param retries - * @return null if no old value for this pin - * @throws at.gv.egiz.smcc.CancelledException if cancelled by user - * @throws java.lang.InterruptedException - */ - public char[] provideOldPIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException; - -} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java index 831a1f9b..64389190 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java @@ -17,6 +17,7 @@ package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.PINGUI; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -96,7 +97,7 @@ public class ITCard extends AbstractSignatureCard { @Override @Exclusive - public byte[] getInfobox(String infobox, PINProvider provider, String domainId) + public byte[] getInfobox(String infobox, PINGUI provider, String domainId) throws SignatureCardException, InterruptedException { throw new IllegalArgumentException("Infobox '" + infobox @@ -106,7 +107,7 @@ public class ITCard extends AbstractSignatureCard { @Override @Exclusive public byte[] createSignature(InputStream input, KeyboxName keyboxName, - PINProvider provider, String alg) throws SignatureCardException, + PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException { if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { @@ -159,7 +160,7 @@ public class ITCard extends AbstractSignatureCard { } protected void verifyPINLoop(CardChannel channel, PINSpec spec, - PINProvider provider) throws LockedException, NotActivatedException, + PINGUI provider) throws LockedException, NotActivatedException, SignatureCardException, InterruptedException, CardException { int retries = -1; @@ -169,7 +170,7 @@ public class ITCard extends AbstractSignatureCard { } protected int verifyPIN(CardChannel channel, PINSpec pinSpec, - PINProvider provider, int retries) throws SignatureCardException, + PINGUI provider, int retries) throws SignatureCardException, LockedException, NotActivatedException, InterruptedException, CardException { @@ -180,7 +181,7 @@ public class ITCard extends AbstractSignatureCard { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }, 0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8); - ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); + ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries); if (resp.getSW() == 0x9000) { return -2; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java index eaf38435..24dfa53c 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java @@ -23,23 +23,4 @@ package at.gv.egiz.smcc; * @author Clemens Orthacker */ public class PINConfirmationException extends SignatureCardException { - - private static final long serialVersionUID = 1L; - - public PINConfirmationException() { - super(); - } - - public PINConfirmationException(String message, Throwable cause) { - super(message, cause); - } - - public PINConfirmationException(String message) { - super(message); - } - - public PINConfirmationException(Throwable cause) { - super(cause); - } - } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java index 774fcdf5..721c63e2 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java @@ -23,23 +23,4 @@ package at.gv.egiz.smcc; * @author Clemens Orthacker */ public class PINFormatException extends SignatureCardException { - - private static final long serialVersionUID = 1L; - - public PINFormatException() { - super(); - } - - public PINFormatException(String message, Throwable cause) { - super(message, cause); - } - - public PINFormatException(String message) { - super(message); - } - - public PINFormatException(Throwable cause) { - super(cause); - } - } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java index 53738612..5091c10f 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java @@ -16,6 +16,9 @@ */ package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; + +import at.gv.egiz.smcc.pin.gui.PINGUI; import java.util.List; public interface PINMgmtSignatureCard extends SignatureCard { @@ -26,16 +29,16 @@ public interface PINMgmtSignatureCard extends SignatureCard { public PIN_STATE getPINState(PINSpec pinSpec) throws SignatureCardException; - public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + public void verifyPIN(PINSpec pinSpec, PINGUI pinGUI) throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException; - public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) + public void changePIN(PINSpec pinSpec, ModifyPINGUI changePINGUI) throws LockedException, NotActivatedException, CancelledException, PINFormatException, SignatureCardException, InterruptedException; - public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) + public void activatePIN(PINSpec pinSpec, ModifyPINGUI activatePINGUI) throws CancelledException, SignatureCardException, InterruptedException; - public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) + public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pukGUI) throws CancelledException, SignatureCardException, InterruptedException; } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java deleted file mode 100644 index 5c294b5b..00000000 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java +++ /dev/null @@ -1,45 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* 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 at.gv.egiz.smcc; - -/** - * The number of retries is not fixed and there is no way (?) to obtain this value. - * A PINProvider should therefore maintain an internal retry counter or flag - * to decide whether or not to warn the user (num retries passed in providePIN). - * - * Therefore PINProvider objects should not be reused. - * - * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated) - * - * @author Clemens Orthacker - */ -public interface PINProvider { - - /** - * - * @param spec - * @param retries num of remaining retries or -1 if unknown - * (a positive value does not necessarily signify that there was - * already an unsuccessful PIN verification) - * @return pin != null - * @throws at.gv.egiz.smcc.CancelledException - * @throws java.lang.InterruptedException - */ - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException; - -} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java b/smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java new file mode 100644 index 00000000..7e71eb7e --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java @@ -0,0 +1,38 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc; + +public class ResetRetryCounterAPDUSpec extends ChangeReferenceDataAPDUSpec { + + /** + * @param apdu + * @param pukPosition + * @param pukFormat + * @param pukLength + * @param pukLengthSize + * @param pukLengthPos + * @param pinInsertionOffsetNew + */ + public ResetRetryCounterAPDUSpec(byte[] apdu, int pukPosition, + int pukFormat, int pukLength, int pukLengthSize, int pukLengthPos, + int pinInsertionOffsetNew) { + super(apdu, pukPosition, pukFormat, pukLength, pukLengthSize, pukLengthPos); + this.pinInsertionOffsetNew = pinInsertionOffsetNew; + } + + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java index 79a4cc69..ad05352f 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -17,6 +17,8 @@ package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -225,7 +227,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu @Override @Exclusive - public byte[] getInfobox(String infobox, PINProvider provider, String domainId) + public byte[] getInfobox(String infobox, PINGUI pinGUI, String domainId) throws SignatureCardException, InterruptedException { try { @@ -243,7 +245,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu try { return ISO7816Utils.readTransparentFileTLV(channel, -1, (byte) 0x30); } catch (SecurityStatusNotSatisfiedException e) { - verifyPINLoop(channel, spec, provider); + verifyPINLoop(channel, spec, pinGUI); } } @@ -301,7 +303,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu @Override @Exclusive public byte[] createSignature(InputStream input, KeyboxName keyboxName, - PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { + PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException { ByteArrayOutputStream dst = new ByteArrayOutputStream(); byte[] ht = null; @@ -431,7 +433,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu */ @Override @Exclusive - public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + public void verifyPIN(PINSpec pinSpec, PINGUI pinProvider) throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { @@ -442,12 +444,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu // SELECT application execSELECT_AID(channel, pinSpec.getContextAID()); } - log.debug("*** verifyPIN loop"); verifyPINLoop(channel, pinSpec, pinProvider); -// log.debug("*** verifyPIN 0"); -// int retries = verifyPIN(channel, pinSpec, null, 0); -// log.debug("*** verifyPIN " + retries + " tries"); -// verifyPIN(channel, pinSpec, pinProvider, retries); } catch (CardException e) { log.info("Failed to verify PIN.", e); throw new SignatureCardException("Failed to verify PIN.", e); @@ -460,7 +457,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu */ @Override @Exclusive - public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) + public void changePIN(PINSpec pinSpec, ModifyPINGUI pinGUI) throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { @@ -471,9 +468,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu // SELECT application execSELECT_AID(channel, pinSpec.getContextAID()); } - changePINLoop(channel, pinSpec, pinProvider); -// int retries = verifyPIN(channel, pinSpec, null, 0); -// changePIN(channel, pinSpec, pinProvider, retries); + changePINLoop(channel, pinSpec, pinGUI); } catch (CardException e) { log.info("Failed to change PIN.", e); throw new SignatureCardException("Failed to change PIN.", e); @@ -486,7 +481,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu */ @Override @Exclusive - public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) + public void activatePIN(PINSpec pinSpec, ModifyPINGUI activatePINGUI) throws CancelledException, SignatureCardException, CancelledException, TimeoutException, InterruptedException { @@ -497,7 +492,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu // SELECT application execSELECT_AID(channel, pinSpec.getContextAID()); } - activatePIN(channel, pinSpec, pinProvider); + activatePIN(channel, pinSpec, activatePINGUI); } catch (CardException e) { log.info("Failed to activate PIN.", e); throw new SignatureCardException("Failed to activate PIN.", e); @@ -509,9 +504,16 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu * @see at.gv.egiz.smcc.PINMgmtSignatureCard#unblockPIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider) */ @Override - public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) + public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pukProvider) throws CancelledException, SignatureCardException, InterruptedException { - throw new SignatureCardException("Unblock PIN is not supported."); + CardChannel channel = getCardChannel(); + + try { + unblockPINLoop(channel, pinSpec, pukProvider); + } catch (CardException e) { + log.info("Failed to activate PIN.", e); + throw new SignatureCardException("Failed to activate PIN.", e); + } } @Override @@ -574,7 +576,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu // PROTECTED METHODS (assume exclusive card access) //////////////////////////////////////////////////////////////////////// - protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINProvider provider) + protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINGUI provider) throws LockedException, NotActivatedException, SignatureCardException, InterruptedException, CardException { @@ -584,7 +586,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu } while (retries > 0); } - protected void changePINLoop(CardChannel channel, PINSpec spec, ChangePINProvider provider) + protected void changePINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider) throws LockedException, NotActivatedException, SignatureCardException, InterruptedException, CardException { @@ -594,8 +596,19 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu } while (retries > 0); } + protected void unblockPINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider) + throws LockedException, NotActivatedException, SignatureCardException, + InterruptedException, CardException { + + //TODO get PUK retry counter from EF FID 0036 in MF + int retries = -1; + do { + retries = unblockPIN(channel, spec, provider, retries); + } while (retries > 0); + } + protected int verifyPIN(CardChannel channel, PINSpec pinSpec, - PINProvider provider, int retries) throws SignatureCardException, + PINGUI provider, int retries) throws SignatureCardException, LockedException, NotActivatedException, InterruptedException, CardException { @@ -608,108 +621,135 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu ResponseAPDU resp; if (provider != null) { - resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); + resp = reader.verify(channel, apduSpec, provider, pinSpec, retries); } else { resp = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, pinSpec.getKID())); } - + + if (resp.getSW() == 0x9000) { return -1; - } - if (resp.getSW() == 0x63c0) { - // returned by the 'short' VERIFY + } else if (resp.getSW() == 0x6983 || resp.getSW() == 0x63c0) { + // authentication method blocked (0x63c0 returned by 'short' VERIFY) throw new LockedException(); - } - if (resp.getSW() >> 4 == 0x63c) { - return 0x0f & resp.getSW(); - } - - switch (resp.getSW()) { - case 0x6983: - // authentication method blocked - // returned by the 'long' VERIFY - throw new LockedException(); - case 0x6984: - // reference data not usable + } else if (resp.getSW() == 0x6984 || resp.getSW() == 0x6985) { + // reference data not usable; conditions of use not satisfied throw new NotActivatedException(); - case 0x6985: - // conditions of use not satisfied + } else if (resp.getSW() >> 4 == 0x63c) { + return 0x0f & resp.getSW(); + } else if (version > 1.2 && resp.getSW() == 0x6400) { + log.warn("cannot query pin status prior to card activation"); throw new NotActivatedException(); - - default: + } else { String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW()); log.info(msg); throw new SignatureCardException(msg); } - } protected int changePIN(CardChannel channel, PINSpec pinSpec, - ChangePINProvider pinProvider, int retries) throws CancelledException, + ModifyPINGUI pinProvider, int retries) throws CancelledException, InterruptedException, CardException, SignatureCardException { - - ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec( - new byte[] { - (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10, - (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff }, + + ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec( + new byte[] { + (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10, + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff }, 1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4, 8); - - ResponseAPDU resp = reader.modify(channel, apduSpec, pinSpec, pinProvider, retries); - + + ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinSpec, retries); + if (resp.getSW() == 0x9000) { return -1; - } - if (resp.getSW() >> 4 == 0x63c) { - return 0x0f & resp.getSW(); - } - - switch (resp.getSW()) { - case 0x6983: + } else if (resp.getSW() == 0x6983) { // authentication method blocked throw new LockedException(); - - default: + } else if (resp.getSW() == 0x6984) { + throw new NotActivatedException(); + } else if (resp.getSW() >> 4 == 0x63c) { + return 0x0f & resp.getSW(); + } else { String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW()); log.info(msg); throw new SignatureCardException(msg); } - - } protected int activatePIN(CardChannel channel, PINSpec pinSpec, - PINProvider provider) throws SignatureCardException, + ModifyPINGUI provider) throws SignatureCardException, InterruptedException, CardException { - NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec( + ResponseAPDU resp; + if (version < 1.2) { + NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec( + new byte[] { + (byte) 0x00, (byte) 0x24, (byte) 0x01, pinSpec.getKID(), (byte) 0x08, + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff }, + 1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); + + resp = reader.modify(channel, apduSpec, provider, pinSpec); + } else { + NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec( + new byte[] { + (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10, + (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff }, + 1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); + apduSpec.setPinInsertionOffsetNew(8); + resp = reader.modify(channel, apduSpec, provider, pinSpec); + } + + if (resp.getSW() == 0x9000) { + return -1; + } else { + String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW()); + log.info(msg); + throw new SignatureCardException(msg); + } + } + + protected int unblockPIN(CardChannel channel, PINSpec pinSpec, + ModifyPINGUI provider, int retries) throws SignatureCardException, + InterruptedException, CardException { + + if (version < 1.2) { + // would return 0x6982 (Security status not satisfied) + throw new SignatureCardException("RESET RETRY COUNTER is not supported by this card."); + } + + ResetRetryCounterAPDUSpec apduSpec = new ResetRetryCounterAPDUSpec( new byte[] { - (byte) 0x00, (byte) 0x24, (byte) 0x01, pinSpec.getKID(), (byte) 0x08, + (byte) 0x00, (byte) 0x2c, (byte) 0x00, pinSpec.getKID(), (byte) 0x10, (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff }, - 1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); - - ResponseAPDU resp = reader.activate(channel, apduSpec, pinSpec, provider); - - switch (resp.getSW()) { - - case 0x9000: - return -1; + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff }, + 1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4, 8); - case 0x6983: - // authentication method blocked - throw new LockedException(); + ResponseAPDU resp = reader.modify(channel, apduSpec, provider, pinSpec, retries); - default: - String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW()); + if (resp.getSW() == 0x9000) { + return -1; + } else if (resp.getSW() == 0x6983) { + // PUK blocked + throw new LockedException(); + } else if (resp.getSW() == 0x6984) { + throw new NotActivatedException(); + } else if (resp.getSW() >> 4 == 0x63c) { + return 0x0f & resp.getSW(); + } else { + String msg = "RESET RETRY COUNTER failed. SW=" + Integer.toHexString(resp.getSW()); log.info(msg); throw new SignatureCardException(msg); } - } - + protected void execSELECT_MF(CardChannel channel) throws CardException, SignatureCardException { ResponseAPDU resp = channel.transmit( new CommandAPDU(0x00, 0xA4, 0x00, 0x0C)); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java index 670704d5..73c7faa8 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -40,15 +40,12 @@ import java.util.Enumeration; import java.util.Locale; import javax.smartcardio.Card; -import javax.smartcardio.CardChannel; -import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; -import javax.smartcardio.ResponseAPDU; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import at.gv.egiz.smcc.ccid.CCID; +import at.gv.egiz.smcc.pin.gui.PINGUI; /** * @@ -280,7 +277,7 @@ public class SWCard implements SignatureCard { } - public byte[] getInfobox(String infobox, PINProvider provider, String domainId) throws SignatureCardException { + public byte[] getInfobox(String infobox, PINGUI provider, String domainId) throws SignatureCardException { String fileName = getFileName(infobox + ".ibx"); FileInputStream file; @@ -309,7 +306,7 @@ public class SWCard implements SignatureCard { } @Override - public byte[] createSignature(InputStream input, KeyboxName keyboxName, PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { + public byte[] createSignature(InputStream input, KeyboxName keyboxName, PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException { // KeyStore password char[] password = getPassword(keyboxName); @@ -396,101 +393,4 @@ public class SWCard implements SignatureCard { @Override public void reset() throws SignatureCardException { } - - @Override - public CCID getReader() { - return new CCID() { - - @Override - public boolean hasFeature(Byte feature) { - return false; - } - - @Override - public byte getbTimeOut() { - return 0; - } - - @Override - public byte getbTimeOut2() { - return 0; - } - - @Override - public byte getwPINMaxExtraDigitL() { - return 0x12; - } - - @Override - public byte getwPINMaxExtraDigitH() { - return 0x00; - } - - @Override - public byte getbEntryValidationCondition() { - return 0x02; - } - - @Override - public Card connect() { - return null; - } - - @Override - public String getName() { - return "Software CardReader"; - } - - @Override - public byte[] verifyPin(byte[] PIN_VERIFY) throws CardException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public byte[] verifyPinDirect(byte[] PIN_VERIFY) throws CardException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public byte[] modifyPin(byte[] PIN_MODIFY) throws CardException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public byte[] modifyPinDirect(byte[] PIN_MODIFY) throws CardException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void setDisablePinpad(boolean disable) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, - PINSpec pinSpec, PINProvider provider, int retries) - throws CancelledException, InterruptedException, CardException, - SignatureCardException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public ResponseAPDU activate(CardChannel channel, - NewReferenceDataAPDUSpec apduSpec, PINSpec pinSpec, - PINProvider provider) throws CancelledException, - InterruptedException, CardException, SignatureCardException { - // TODO Auto-generated method stub - return null; - } - - @Override - public ResponseAPDU modify(CardChannel channel, - ChangeReferenceDataAPDUSpec apduSpec, PINSpec pinSpec, - ChangePINProvider provider, int retries) throws CancelledException, - InterruptedException, CardException, SignatureCardException { - // TODO Auto-generated method stub - return null; - } - }; - } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index 3d56f97b..fa589b84 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -17,8 +17,7 @@ package at.gv.egiz.smcc; -import at.gv.egiz.smcc.ccid.CCID; - +import at.gv.egiz.smcc.pin.gui.PINGUI; import java.io.IOException; import java.io.InputStream; import java.util.Locale; @@ -99,7 +98,7 @@ public interface SignatureCard { * @throws SignatureCardException * @throws InterruptedException if applet is destroyed while in pin dialog */ - public byte[] getInfobox(String infobox, PINProvider provider, String domainId) + public byte[] getInfobox(String infobox, PINGUI pinGUI, String domainId) throws SignatureCardException, InterruptedException; /** @@ -114,9 +113,7 @@ public interface SignatureCard { * @throws IOException */ public byte[] createSignature(InputStream input, KeyboxName keyboxName, - PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException; - - public CCID getReader(); + PINGUI pinGUI, String alg) throws SignatureCardException, InterruptedException, IOException; /** * Sets the local for evtl. required callbacks (e.g. PINSpec) diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java new file mode 100644 index 00000000..00dc2d0e --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java @@ -0,0 +1,36 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + + +public interface ModifyPINGUI extends ModifyPINProvider { + + void modifyPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException; + void finishDirect(); + + void enterCurrentPIN(PINSpec spec, int retries); + void enterNewPIN(PINSpec spec); + void confirmNewPIN(PINSpec spec); + void validKeyPressed(); + void correctionButtonPressed(); + void allKeysCleared(); + /** called prior to MODIFY_PIN_FINISH control command transmission (clear display or display wait message) */ + void finish(); +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java new file mode 100644 index 00000000..36f0097d --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java @@ -0,0 +1,48 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + + +/** + * user interface for "software pin-entry" of + *
    + *
  • current pin and new pin (change pin) + *
  • new pin (pin activation, no current pin) + *
  • puk and new pin (probably verify only?) + *
+ * @author Clemens Orthacker + */ +public interface ModifyPINProvider { + + /** + * + * @param spec + * @param retries + * @return null if no old value for this pin + * @throws at.gv.egiz.smcc.CancelledException if cancelled by user + * @throws java.lang.InterruptedException + */ + public char[] provideCurrentPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException; + + public char[] provideNewPIN(PINSpec spec) + throws CancelledException, InterruptedException; + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java new file mode 100644 index 00000000..5199977b --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java @@ -0,0 +1,42 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + + +/** + * Display messages for pinpad pin-entry. + * Provides an interface for two types of pinpad pin-entry: pinpad-direct and pinpad-start/finish + * @author clemens.orthacker@iaik.tugraz.at + */ +public interface PINGUI extends PINProvider { + + void enterPINDirect(PINSpec spec, int retries) + throws CancelledException, InterruptedException; + + /** + * @throws CancelledException, InterruptedException if signature-data dialog is interrupted or cancelled + */ + void enterPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException; + void validKeyPressed(); + void correctionButtonPressed(); + void allKeysCleared(); + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java new file mode 100644 index 00000000..3bf49888 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java @@ -0,0 +1,49 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + + +/** + * The number of retries is not fixed and there is no way (?) to obtain this value. + * A PINProvider should therefore maintain an internal retry counter or flag + * to decide whether or not to warn the user (num retries passed in providePIN). + * + * Therefore PINProvider objects should not be reused. + * + * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated) + * + * @author Clemens Orthacker + */ +public interface PINProvider { + + /** + * + * @param spec + * @param retries num of remaining retries or -1 if unknown + * (a positive value does not necessarily signify that there was + * already an unsuccessful PIN verification) + * @return pin != null + * @throws at.gv.egiz.smcc.CancelledException + * @throws java.lang.InterruptedException + */ + char[] providePIN(PINSpec pinSpec, int retries) + throws CancelledException, InterruptedException; + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java new file mode 100644 index 00000000..a1246dd6 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java @@ -0,0 +1,92 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.reader; + +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.ResponseAPDU; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import javax.smartcardio.Card; + +/** + * + * @author Clemens Orthacker + */ +public interface CardReader { + + + String[] FEATURES = new String[]{"NO_FEATURE", + "FEATURE_VERIFY_PIN_START", + "FEATURE_VERIFY_PIN_FINISH", + "FEATURE_MODIFY_PIN_START", + "FEATURE_MODIFY_PIN_FINISH", + "FEATURE_GET_KEY_PRESSED", + "FEATURE_VERIFY_PIN_DIRECT", + "FEATURE_MODIFY_PIN_DIRECT", + "FEATURE_MCT_READER_DIRECT", + "FEATURE_MCT_UNIVERSAL", + "FEATURE_IFD_PIN_PROPERTIES", + "FEATURE_ABORT", + "FEATURE_SET_SPE_MESSAGE", + "FEATURE_VERIFY_PIN_DIRECT_APP_ID", + "FEATURE_MODIFY_PIN_DIRECT_APP_ID", + "FEATURE_WRITE_DISPLAY", + "FEATURE_GET_KEY", + "FEATURE_IFD_DISPLAY_PROPERTIES"}; + + Byte FEATURE_VERIFY_PIN_START = new Byte((byte) 0x01); + Byte FEATURE_VERIFY_PIN_FINISH = new Byte((byte) 0x02); + Byte FEATURE_MODIFY_PIN_START = new Byte((byte) 0x03); + Byte FEATURE_MODIFY_PIN_FINISH = new Byte((byte) 0x04); + Byte FEATURE_GET_KEY_PRESSED = new Byte((byte) 0x05); + Byte FEATURE_VERIFY_PIN_DIRECT = new Byte((byte) 0x06); + Byte FEATURE_MODIFY_PIN_DIRECT = new Byte((byte) 0x07); + Byte FEATURE_MCT_READER_DIRECT = new Byte((byte) 0x08); + Byte FEATURE_MCT_UNIVERSAL = new Byte((byte) 0x09); + Byte FEATURE_IFD_PIN_PROPERTIES = new Byte((byte) 0x0a); + //TODO continue list + + + Card connect() throws CardException; + + boolean hasFeature(Byte feature); + + ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, + PINGUI pinGUI, PINSpec pinSpec, int retries) + throws CancelledException, InterruptedException, CardException, SignatureCardException; + + ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec, + ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) + throws CancelledException, InterruptedException, CardException, SignatureCardException; + + ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec, + ModifyPINGUI pinGUI, PINSpec pinSpec) + throws CancelledException, InterruptedException, CardException, SignatureCardException; + + ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec, + ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) + throws CancelledException, InterruptedException, CardException, SignatureCardException; +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java new file mode 100644 index 00000000..45ea7a5a --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java @@ -0,0 +1,106 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.reader; + + +import javax.smartcardio.Card; +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.util.ISO7816Utils; + +/** + * + * @author Clemens Orthacker + */ +public class DefaultCardReader implements CardReader { + + protected final static Log log = LogFactory.getLog(DefaultCardReader.class); + + protected CardTerminal ct; + protected String name; + + public DefaultCardReader(CardTerminal ct) { + if (ct == null) { + throw new NullPointerException("no card or card terminal provided"); + } + this.ct = ct; + this.name = ct.getName(); + } + + @Override + public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, + PINGUI pinGUI, PINSpec pinSpec, int retries) + throws SignatureCardException, CardException, InterruptedException { + + log.debug("VERIFY"); + return channel.transmit(ISO7816Utils.createVerifyAPDU(apduSpec, pinGUI.providePIN(pinSpec, retries))); + } + + @Override + public ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec, + ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) + throws SignatureCardException, CardException, InterruptedException { + log.debug("MODIFY (CHANGE_REFERENCE_DATA)"); + char[] oldPin = pinGUI.provideCurrentPIN(pinSpec, retries); + char[] newPin = pinGUI.provideNewPIN(pinSpec); + return channel.transmit(ISO7816Utils.createChangeReferenceDataAPDU(apduSpec, oldPin, newPin)); + } + + @Override + public ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec, + ModifyPINGUI pinGUI, PINSpec pinSpec) + throws SignatureCardException, CardException, InterruptedException { + log.debug("MODIFY (NEW_REFERENCE_DATA)"); + char[] newPIN = pinGUI.provideNewPIN(pinSpec); + return channel.transmit(ISO7816Utils.createNewReferenceDataAPDU(apduSpec, newPIN)); + } + + @Override + public ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec, + ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) + throws InterruptedException, CardException, SignatureCardException { + log.debug("MODIFY (RESET_RETRY_COUNTER)"); + //TODO + return modify(channel, (ChangeReferenceDataAPDUSpec) apduSpec, pinGUI, pinSpec, retries); + } + + @Override + public Card connect() throws CardException { + log.debug("connect icc"); + return ct.connect("*"); + } + + @Override + public boolean hasFeature(Byte feature) { + return false; + } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java new file mode 100644 index 00000000..c2537af8 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java @@ -0,0 +1,703 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.reader; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Map; + +import javax.smartcardio.Card; +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINConfirmationException; +import at.gv.egiz.smcc.PINFormatException; +import at.gv.egiz.smcc.PINOperationAbortedException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.TimeoutException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.util.SMCCHelper; + +/** + * + * @author Clemens Orthacker + */ +public class PinpadCardReader extends DefaultCardReader { + + public static final int PIN_ENTRY_POLLING_INTERVAL = 10; + + protected final static Log log = LogFactory.getLog(PinpadCardReader.class); + + protected byte bEntryValidationCondition = 0x02; // validation key pressed + protected byte bTimeOut = 0x3c; // 60sec (= max on ReinerSCT) + protected byte bTimeOut2 = 0x00; // default (attention with SCM) + protected byte wPINMaxExtraDigitH = 0x00; // min pin length zero digits + protected byte wPINMaxExtraDigitL = 0x0c; // max pin length 12 digits + + /** + * supported features and respective control codes + */ + protected Map features; + protected boolean VERIFY, MODIFY, VERIFY_DIRECT, MODIFY_DIRECT; + + public PinpadCardReader(CardTerminal ct, Map features) { + super(ct); + if (features == null) { + throw new NullPointerException("Pinpad card reader does not support any features"); + } + this.features = features; + + if (features.containsKey(FEATURE_VERIFY_PIN_START) && + features.containsKey(FEATURE_GET_KEY_PRESSED) && + features.containsKey(FEATURE_VERIFY_PIN_FINISH)) { + VERIFY = true; + } + if (features.containsKey(FEATURE_MODIFY_PIN_START) && + features.containsKey(FEATURE_GET_KEY_PRESSED) && + features.containsKey(FEATURE_MODIFY_PIN_FINISH)) { + MODIFY = true; + } + if (features.containsKey(FEATURE_VERIFY_PIN_DIRECT)) { + VERIFY_DIRECT = true; + } + if (features.containsKey(FEATURE_MODIFY_PIN_DIRECT)) { + MODIFY_DIRECT = true; + } + + if (name != null) { + name = name.toLowerCase(); + //ReinerSCT: http://support.reiner-sct.de/downloads/LINUX + // http://www.linux-club.de/viewtopic.php?f=61&t=101287&start=0 + //old: REINER SCT CyberJack 00 00 + //new (CCID): 0C4B/0300 Reiner-SCT cyberJack pinpad(a) 00 00 + //Snow Leopard: Reiner-SCT cyberJack pinpad(a) 00 00 + //display: REINER SCT CyberJack 00 00 + if(name.startsWith("gemplus gempc pinpad") || name.startsWith("gemalto gempc pinpad")) { + log.debug("setting custom wPINMaxExtraDigitH (0x04) for " + name); + wPINMaxExtraDigitH = 0x04; + log.debug("setting custom wPINMaxExtraDigitL (0x08) for " + name); + wPINMaxExtraDigitL = 0x08; + } else if (name.startsWith("omnikey cardman 3621")) { + log.debug("setting custom wPINMaxExtraDigitH (0x01) for " + name); + wPINMaxExtraDigitH = 0x01; + } else if (name.startsWith("scm spr 532") || name.startsWith("scm microsystems inc. sprx32 usb smart card reader")) { + log.debug("setting custom bTimeOut (0x3c) for " + name); + bTimeOut = 0x3c; + log.debug("setting custom bTimeOut2 (0x0f) for " + name); + bTimeOut2 = 0x0f; + } else if (name.startsWith("cherry smartboard xx44")) { + log.debug("setting custom wPINMaxExtraDigitH (0x01) for " + name); + wPINMaxExtraDigitH = 0x01; + } + } + + } + + @Override + public boolean hasFeature(Byte feature) { + return features.containsKey(feature); + } + + private void VERIFY_PIN_START(Card icc, byte[] PIN_VERIFY) throws CardException { + int ioctl = features.get(FEATURE_VERIFY_PIN_START); + if (log.isTraceEnabled()) { + log.trace("VERIFY_PIN_START (" + Integer.toHexString(ioctl) + + ") " + SMCCHelper.toString(PIN_VERIFY)); + } + byte[] resp = icc.transmitControlCommand(ioctl, PIN_VERIFY); + if (resp != null && resp.length > 0) { + if (resp[0] == (byte) 0x57) { + log.error("Invalid parameter in PIN_VERIFY structure"); + throw new CardException("ERROR_INVALID_PARAMETER"); + } else { + log.error("unexpected response to VERIFY_PIN_START: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to VERIFY_PIN_START: " + + SMCCHelper.toString(resp)); + } + } + } + + private byte GET_KEY_PRESSED(Card icc) throws CardException { + int ioctl = features.get(FEATURE_GET_KEY_PRESSED); + byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); + if (resp != null && resp.length == 1) { +// if (log.isTraceEnabled()) { +// log.trace("response " + SMCCHelper.toString(resp)); +// } + return resp[0]; + } + log.error("unexpected response to GET_KEY_PRESSED: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to GET_KEY_PRESSED: " + + SMCCHelper.toString(resp)); + } + + private byte[] VERIFY_PIN_FINISH(Card icc) throws CardException { + int ioctl = features.get(FEATURE_VERIFY_PIN_FINISH); + if (log.isTraceEnabled()) { + log.trace("VERIFY_PIN_FINISH (" + Integer.toHexString(ioctl) + ")"); + } + byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); + if (resp != null && resp.length == 2) { + if (log.isTraceEnabled()) { + log.trace("response " + SMCCHelper.toString(resp)); + } + return resp; + } + log.error("unexpected response to VERIFY_PIN_FINISH: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to VERIFY_PIN_FINISH: " + + SMCCHelper.toString(resp)); + } + + private void MODIFY_PIN_START(Card icc, byte[] PIN_MODIFY) throws CardException { + int ioctl = features.get(FEATURE_MODIFY_PIN_START); + if (log.isTraceEnabled()) { + log.trace("MODFIY_PIN_START (" + Integer.toHexString(ioctl) + + ") " + SMCCHelper.toString(PIN_MODIFY)); + } + byte[] resp = icc.transmitControlCommand(ioctl, PIN_MODIFY); + if (resp != null && resp.length > 0) { + if (resp[0] == (byte) 0x57) { + log.error("Invalid parameter in PIN_MODIFY structure"); + throw new CardException("ERROR_INVALID_PARAMETER"); + } else { + log.error("unexpected response to MODIFY_PIN_START: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to MODIFY_PIN_START: " + + SMCCHelper.toString(resp)); + } + } + } + + private byte[] MODIFY_PIN_FINISH(Card icc) throws CardException { + int ioctl = features.get(FEATURE_MODIFY_PIN_FINISH); + if (log.isTraceEnabled()) { + log.trace("MODIFY_PIN_FINISH (" + Integer.toHexString(ioctl) + ")"); + } + byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); + if (resp != null && resp.length == 2) { + if (log.isTraceEnabled()) { + log.trace("response " + SMCCHelper.toString(resp)); + } + return resp; + } + log.error("unexpected response to MODIFY_PIN_FINISH: " + + SMCCHelper.toString(resp)); + throw new CardException("unexpected response to MODIFY_PIN_FINISH: " + + SMCCHelper.toString(resp)); + } + + private byte[] VERIFY_PIN_DIRECT(Card icc, byte[] PIN_VERIFY) throws CardException { + int ioctl = features.get(FEATURE_VERIFY_PIN_DIRECT); + if (log.isTraceEnabled()) { + log.trace("VERIFY_PIN_DIRECT (" + Integer.toHexString(ioctl) + + ") " + SMCCHelper.toString(PIN_VERIFY)); + } + byte[] resp = icc.transmitControlCommand(ioctl, PIN_VERIFY); + if (log.isTraceEnabled()) { + log.trace("response " + SMCCHelper.toString(resp)); + } + return resp; + } + + private byte[] verifyPin(Card icc, byte[] PIN_VERIFY, PINGUI pinGUI) + throws SignatureCardException, CardException, InterruptedException { + +// pinGUI.enterPIN(pinSpec, retries); + + log.debug("VERIFY_PIN_START [" + FEATURES[FEATURE_VERIFY_PIN_START] + "]"); + VERIFY_PIN_START(icc, PIN_VERIFY); + + byte resp; + do { + resp = GET_KEY_PRESSED(icc); + if (resp == (byte) 0x00) { + synchronized(this) { + try { + wait(PIN_ENTRY_POLLING_INTERVAL); + } catch (InterruptedException ex) { + log.error("interrupted in VERIFY_PIN"); + } + } + } else if (resp == (byte) 0x0d) { + log.debug("GET_KEY_PRESSED: 0x0d (user confirmed)"); + break; + } else if (resp == (byte) 0x2b) { + log.trace("GET_KEY_PRESSED: 0x2b (user entered valid key 0-9)"); + pinGUI.validKeyPressed(); + } else if (resp == (byte) 0x1b) { + log.debug("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)"); + break; // returns 0x6401 + } else if (resp == (byte) 0x08) { + log.debug("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)"); + pinGUI.correctionButtonPressed(); + } else if (resp == (byte) 0x0e) { + log.debug("GET_KEY_PRESSED: 0x0e (timeout occured)"); + break; // return 0x6400 + } else if (resp == (byte) 0x40) { + log.debug("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)"); + throw new PINOperationAbortedException("PIN_Operation_Aborted (0x40)"); + } else if (resp == (byte) 0x0a) { + log.debug("GET_KEY_PRESSED: 0x0a (all keys cleared"); + pinGUI.allKeysCleared(); + } else { + log.error("unexpected response to GET_KEY_PRESSED: " + + Integer.toHexString(resp)); + throw new CardException("unexpected response to GET_KEY_PRESSED: " + + Integer.toHexString(resp)); + } + } while (true); + + return VERIFY_PIN_FINISH(icc); + } + + /** + * does not display the first pin dialog (enterCurrentPIN or enterNewPIN, depends on bConfirmPIN), + * since this is easier to do in calling modify() + */ + private byte[] modifyPin(Card icc, byte[] PIN_MODIFY, ModifyPINGUI pinGUI, PINSpec pINSpec) + throws PINOperationAbortedException, CardException { + + byte pinConfirmations = (byte) 0x00; //b0: new pin not entered (0) / entered (1) + //b1: current pin not entered (0) / entered (1) + byte bConfirmPIN = PIN_MODIFY[9]; + +// if ((bConfirmPIN & (byte) 0x02) == 0) { +// log.debug("no current PIN entry requested"); +// pinGUI.enterNewPIN(pINSpec); +// } else { +// log.debug("current PIN entry requested"); +// pinGUI.enterCurrentPIN(pINSpec, retries); +// } + + log.debug("MODIFY_PIN_START [" + FEATURES[FEATURE_MODIFY_PIN_START] + "]"); + MODIFY_PIN_START(icc, PIN_MODIFY); + + byte resp; + while (true) { + resp = GET_KEY_PRESSED(icc); + if (resp == (byte) 0x00) { + synchronized(this) { + try { + wait(PIN_ENTRY_POLLING_INTERVAL); + } catch (InterruptedException ex) { + log.error("interrupted in MODIFY_PIN"); + } + } + } else if (resp == (byte) 0x0d) { + if (log.isTraceEnabled()) { + log.trace("requested pin confirmations: 0b" + Integer.toBinaryString(bConfirmPIN & 0xff)); + log.trace("performed pin confirmations: 0b" + Integer.toBinaryString(pinConfirmations & 0xff)); + } + log.debug("GET_KEY_PRESSED: 0x0d (user confirmed)"); + if (pinConfirmations == bConfirmPIN) { + break; + } else if ((bConfirmPIN & (byte) 0x02) == 0 || + (pinConfirmations & (byte) 0x02) == (byte) 0x02) { + // no current pin entry or current pin entry already performed + if ((pinConfirmations & (byte) 0x01) == 0) { + // new pin + pinConfirmations |= (byte) 0x01; + pinGUI.confirmNewPIN(pINSpec); + } // else: new pin confirmed + } else { + // current pin entry + pinConfirmations |= (byte) 0x02; + pinGUI.enterNewPIN(pINSpec); + } + } else if (resp == (byte) 0x2b) { + log.trace("GET_KEY_PRESSED: 0x2b (user entered valid key 0-9)"); + pinGUI.validKeyPressed(); + } else if (resp == (byte) 0x1b) { + log.debug("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)"); + break; // returns 0x6401 + } else if (resp == (byte) 0x08) { + log.debug("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)"); + pinGUI.correctionButtonPressed(); + } else if (resp == (byte) 0x0e) { + log.debug("GET_KEY_PRESSED: 0x0e (timeout occured)"); + break; // return 0x6400 + } else if (resp == (byte) 0x40) { + log.debug("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)"); + throw new PINOperationAbortedException("PIN_Operation_Aborted (0x40)"); + } else if (resp == (byte) 0x0a) { + log.debug("GET_KEY_PRESSED: 0x0a (all keys cleared"); + pinGUI.allKeysCleared(); + } else { + log.error("unexpected response to GET_KEY_PRESSED: " + + Integer.toHexString(resp)); + throw new CardException("unexpected response to GET_KEY_PRESSED: " + + Integer.toHexString(resp)); + } + + } + + pinGUI.finish(); + return MODIFY_PIN_FINISH(icc); + } + + private byte[] MODIFY_PIN_DIRECT(Card icc, byte[] PIN_MODIFY) throws CardException { + int ioctl = features.get(FEATURE_MODIFY_PIN_DIRECT); + if (log.isTraceEnabled()) { + log.trace("MODIFY_PIN_DIRECT (" + Integer.toHexString(ioctl) + + ") " + SMCCHelper.toString(PIN_MODIFY)); + } + byte[] resp = icc.transmitControlCommand(ioctl, PIN_MODIFY); + if (log.isTraceEnabled()) { + log.trace("response " + SMCCHelper.toString(resp)); + } + return resp; + } + + protected byte[] createPINModifyStructure(NewReferenceDataAPDUSpec apduSpec, PINSpec pinSpec) { + + ByteArrayOutputStream s = new ByteArrayOutputStream(); + // bTimeOut + s.write(bTimeOut); + // bTimeOut2 + s.write(bTimeOut2); + // bmFormatString + s.write(1 << 7 // system unit = byte + | (0xF & apduSpec.getPinPosition()) << 3 + | (0x1 & apduSpec.getPinJustification() << 2) + | (0x3 & apduSpec.getPinFormat())); + // bmPINBlockString + s.write((0xF & apduSpec.getPinLengthSize()) << 4 + | (0xF & apduSpec.getPinLength())); + // bmPINLengthFormat + s.write(// system unit = bit + (0xF & apduSpec.getPinLengthPos())); + // bInsertionOffsetOld + s.write(0x00); + // bInsertionOffsetNew + s.write(apduSpec.getPinInsertionOffsetNew()); + // wPINMaxExtraDigit + s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL)); + s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); + // bConfirmPIN + s.write(0x01); + // bEntryValidationCondition + s.write(bEntryValidationCondition); + // bNumberMessage + s.write(0x02); + // wLangId English (United States), see http://www.usb.org/developers/docs/USB_LANGIDs.pdf + s.write(0x09); + s.write(0x04); + // bMsgIndex1 + s.write(0x01); + // bMsgIndex2 + s.write(0x02); + // bMsgIndex3 + s.write(0x00); + + // bTeoPrologue + s.write(0x00); + s.write(0x00); + s.write(0x00); + // ulDataLength + s.write(apduSpec.getApdu().length); + s.write(0x00); + s.write(0x00); + s.write(0x00); + // abData + try { + s.write(apduSpec.getApdu()); + } catch (IOException e) { + // As we are dealing with ByteArrayOutputStreams no exception is to be + // expected. + throw new RuntimeException(e); + } + + return s.toByteArray(); + + } + + protected byte[] createPINModifyStructure(ChangeReferenceDataAPDUSpec apduSpec, PINSpec pinSpec) { + //TODO bInsertionOffsetOld (0x00), bConfirmPIN (0x01), bNumberMessage (0x02), bMsgIndex1/2/3 + + ByteArrayOutputStream s = new ByteArrayOutputStream(); + // bTimeOut + s.write(bTimeOut); + // bTimeOut2 + s.write(bTimeOut2); + // bmFormatString + s.write(1 << 7 // system unit = byte + | (0xF & apduSpec.getPinPosition()) << 3 + | (0x1 & apduSpec.getPinJustification() << 2) + | (0x3 & apduSpec.getPinFormat())); + // bmPINBlockString + s.write((0xF & apduSpec.getPinLengthSize()) << 4 + | (0xF & apduSpec.getPinLength())); + // bmPINLengthFormat + s.write(// system unit = bit + (0xF & apduSpec.getPinLengthPos())); + // bInsertionOffsetOld (0x00 for no old pin?) + s.write(apduSpec.getPinInsertionOffsetOld()); + // bInsertionOffsetNew + s.write(apduSpec.getPinInsertionOffsetNew()); + // wPINMaxExtraDigit + s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL)); + s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); + // bConfirmPIN + s.write(0x03); + // bEntryValidationCondition + s.write(bEntryValidationCondition); + // bNumberMessage + s.write(0x03); + // wLangId English (United States), see http://www.usb.org/developers/docs/USB_LANGIDs.pdf + s.write(0x09); + s.write(0x04); + // bMsgIndex1 + s.write(0x00); + // bMsgIndex2 + s.write(0x01); + // bMsgIndex3 + s.write(0x02); + + // bTeoPrologue + s.write(0x00); + s.write(0x00); + s.write(0x00); + // ulDataLength + s.write(apduSpec.getApdu().length); + s.write(0x00); + s.write(0x00); + s.write(0x00); + // abData + try { + s.write(apduSpec.getApdu()); + } catch (IOException e) { + // As we are dealing with ByteArrayOutputStreams no exception is to be + // expected. + throw new RuntimeException(e); + } + + return s.toByteArray(); + + } + + protected byte[] createPINVerifyStructure(VerifyAPDUSpec apduSpec, PINSpec pinSpec) { + + ByteArrayOutputStream s = new ByteArrayOutputStream(); + // bTimeOut + s.write(bTimeOut); + // bTimeOut2 + s.write(bTimeOut2); + // bmFormatString + s.write(1 << 7 // system unit = byte + | (0xF & apduSpec.getPinPosition()) << 3 + | (0x1 & apduSpec.getPinJustification() << 2) + | (0x3 & apduSpec.getPinFormat())); + // bmPINBlockString + s.write((0xF & apduSpec.getPinLengthSize()) << 4 + | (0xF & apduSpec.getPinLength())); + // bmPINLengthFormat + s.write(// system unit = bit + (0xF & apduSpec.getPinLengthPos())); + // wPINMaxExtraDigit + s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL)); // max PIN length + s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); // min PIN length + // bEntryValidationCondition + s.write(bEntryValidationCondition); + // bNumberMessage + s.write(0x01); + // wLangId + s.write(0x09); + s.write(0x04); + // bMsgIndex + s.write(0x00); + // bTeoPrologue + s.write(0x00); + s.write(0x00); + s.write(0x00); + // ulDataLength + s.write(apduSpec.getApdu().length); + s.write(0x00); + s.write(0x00); + s.write(0x00); + // abData + try { + s.write(apduSpec.getApdu()); + } catch (IOException e) { + // As we are dealing with ByteArrayOutputStreams no exception is to be + // expected. + throw new RuntimeException(e); + } + + return s.toByteArray(); + + } + + @Override + public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, + PINGUI pinGUI, PINSpec pinSpec, int retries) + throws SignatureCardException, CardException, InterruptedException { + + ResponseAPDU resp = null; + + byte[] s = createPINVerifyStructure(apduSpec, pinSpec); + Card icc = channel.getCard(); + + if (VERIFY) { + pinGUI.enterPIN(pinSpec, retries); + resp = new ResponseAPDU(verifyPin(icc, s, pinGUI)); + } else if (VERIFY_DIRECT) { + pinGUI.enterPINDirect(pinSpec, retries); + log.debug("VERIFY_PIN_DIRECT [" + FEATURES[FEATURE_VERIFY_PIN_DIRECT] + "]"); + resp = new ResponseAPDU(VERIFY_PIN_DIRECT(icc, s)); + } else { + log.warn("falling back to default pin-entry"); + return super.verify(channel, apduSpec, pinGUI, pinSpec, retries); + } + + switch (resp.getSW()) { + case 0x6400: + log.debug("SPE operation timed out."); + throw new TimeoutException(); + case 0x6401: + log.debug("SPE operation was cancelled by the 'Cancel' button."); + throw new CancelledException(); + case 0x6403: + log.debug("User entered too short or too long PIN " + + "regarding MIN/MAX PIN length."); + throw new PINFormatException(); + case 0x6480: + log.debug("SPE operation was aborted by the 'Cancel' operation " + + "at the host system."); + case 0x6b80: + log.info("Invalid parameter in passed structure."); + default: + return resp; + } + } + + @Override + public ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec, + ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) + throws SignatureCardException, CardException, InterruptedException { + + ResponseAPDU resp = null; + + byte[] s = createPINModifyStructure(apduSpec, pinSpec); + Card icc = channel.getCard(); + + if (MODIFY) { + pinGUI.enterCurrentPIN(pinSpec, retries); + resp = new ResponseAPDU(modifyPin(icc, s, pinGUI, pinSpec)); + } else if (MODIFY_DIRECT) { + pinGUI.modifyPINDirect(pinSpec, retries); + log.debug("MODIFY_PIN_DIRECT [" + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "]"); + resp = new ResponseAPDU(MODIFY_PIN_DIRECT(icc, s)); + } else { + log.warn("falling back to default pin-entry"); + return super.modify(channel, apduSpec, pinGUI, pinSpec, retries); + } + + switch (resp.getSW()) { + case 0x6400: + log.debug("SPE operation timed out."); + throw new TimeoutException(); + case 0x6401: + log.debug("SPE operation was cancelled by the 'Cancel' button."); + throw new CancelledException(); + case 0x6402: + log.debug("Modify PIN operation failed because two 'new PIN' " + + "entries do not match"); + throw new PINConfirmationException(); + case 0x6403: + log.debug("User entered too short or too long PIN " + + "regarding MIN/MAX PIN length."); + throw new PINFormatException(); + case 0x6480: + log.debug("SPE operation was aborted by the 'Cancel' operation " + + "at the host system."); + case 0x6b80: + log.info("Invalid parameter in passed structure."); + default: + return resp; + } + } + + @Override + public ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec, + ModifyPINGUI pinGUI, PINSpec pinSpec) + throws SignatureCardException, CardException, InterruptedException { + + ResponseAPDU resp = null; + + byte[] s = createPINModifyStructure(apduSpec, pinSpec); + Card icc = channel.getCard(); + + if (MODIFY) { + pinGUI.enterNewPIN(pinSpec); + resp = new ResponseAPDU(modifyPin(icc, s, pinGUI, pinSpec)); + } else if (MODIFY_DIRECT) { + pinGUI.modifyPINDirect(pinSpec, -1); + log.debug("MODIFY_PIN_DIRECT [" + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "]"); + resp = new ResponseAPDU(MODIFY_PIN_DIRECT(icc, s)); + } else { + log.warn("falling back to default pin-entry"); + return super.modify(channel, apduSpec, pinGUI, pinSpec); + } + + switch (resp.getSW()) { + case 0x6400: + log.debug("SPE operation timed out."); + throw new TimeoutException(); + case 0x6401: + log.debug("SPE operation was cancelled by the 'Cancel' button."); + throw new CancelledException(); + case 0x6402: + log.debug("Modify PIN operation failed because two 'new PIN' " + + "entries do not match"); + throw new PINConfirmationException(); + case 0x6403: + log.debug("User entered too short or too long PIN " + + "regarding MIN/MAX PIN length."); + throw new PINFormatException(); + case 0x6480: + log.debug("SPE operation was aborted by the 'Cancel' operation " + + "at the host system."); + case 0x6b80: + log.info("Invalid parameter in passed structure."); + default: + return resp; + } + } + + @Override + public ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec, + ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) + throws InterruptedException, CardException, SignatureCardException { + //TODO + return modify(channel, (ChangeReferenceDataAPDUSpec) apduSpec, pinGUI, pinSpec, retries); + } +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java new file mode 100644 index 00000000..eb197d9f --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java @@ -0,0 +1,128 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.reader; + +import at.gv.egiz.smcc.conf.SMCCConfiguration; +import at.gv.egiz.smcc.util.SMCCHelper; +import java.util.HashMap; +import java.util.Map; +import javax.smartcardio.Card; +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public class ReaderFactory { + + protected final static Log log = LogFactory.getLog(ReaderFactory.class); + + protected SMCCConfiguration configuration; + + private ReaderFactory() { + } + + /** + * @param configuration the configuration to set + */ + public void setConfiguration(SMCCConfiguration configuration) { + this.configuration = configuration; + } + + public static CardReader getReader(Card icc, CardTerminal ct) { + + String name = ct.getName(); + log.info("creating reader " + name); + + Map features = queryFeatures(icc); + boolean disablePinpad = false; + CardReader reader; + + //TODO query application context for reader config +// if (configuration != null) { +// String disablePinpad = configuration.getProperty(SMCCConfiguration.DISABLE_PINPAD_P); +// log.debug("setting disablePinpad to " + Boolean.parseBoolean(disablePinpad)); +// reader.setDisablePinpad(Boolean.parseBoolean(disablePinpad)); +// } + log.warn("card reader configuration is not considered"); + + if (features.isEmpty() || disablePinpad) { + reader = new DefaultCardReader(ct); + } else { + reader = new PinpadCardReader(ct, features); + } + + return reader; + } + + private static int CTL_CODE(int code) { + String os_name = System.getProperty("os.name").toLowerCase(); + if (os_name.indexOf("windows") > -1) { + // cf. WinIOCTL.h + return (0x31 << 16 | (code) << 2); + } + // cf. reader.h + return 0x42000000 + (code); + } + + static int IOCTL_GET_FEATURE_REQUEST = CTL_CODE(3400); + + private static Map queryFeatures(Card icc) { + Map features = new HashMap(); + + if (icc == null) { + log.warn("invalid card handle, cannot query ifd features"); + } else { + try { + if (log.isTraceEnabled()) { + log.trace("GET_FEATURE_REQUEST " + Integer.toHexString(IOCTL_GET_FEATURE_REQUEST)); + } + byte[] resp = icc.transmitControlCommand(IOCTL_GET_FEATURE_REQUEST, + new byte[0]); + + if (log.isTraceEnabled()) { + log.trace("Response TLV " + SMCCHelper.toString(resp)); + } + // tag + // length in bytes (always 4) + // control code value for supported feature (in big endian) + for (int i = 0; i < resp.length; i += 6) { + Byte feature = new Byte(resp[i]); + Integer ioctl = new Integer((0xff & resp[i + 2]) << 24) | + ((0xff & resp[i + 3]) << 16) | + ((0xff & resp[i + 4]) << 8) | + (0xff & resp[i + 5]); + if (log.isInfoEnabled()) { + log.info("IFD supports " + CardReader.FEATURES[feature.intValue()] + + ": " + Integer.toHexString(ioctl.intValue())); + } + features.put(feature, ioctl); + } + } catch (CardException ex) { + log.debug("Failed to query IFD features: " + ex.getMessage()); + log.trace(ex); + log.info("IFD does not support secure pin entry"); + } + } + return features; + } + +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java b/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java index 137de509..affb06ff 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java @@ -51,6 +51,7 @@ public abstract class AbstractAppl implements CardAppl { return files; } + @Override public abstract void setPin(int kid, char[] value); } \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java index 6017bcce..3dfc8510 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java @@ -28,15 +28,15 @@ import javax.smartcardio.CardException; @SuppressWarnings("restriction") public abstract class CardEmul extends Card { - protected Thread exclThread = null; - protected CardChannel channel = newCardChannel(this); + protected Thread exclThread; // = null; + protected CardChannel channel; // = newCardChannel(this); protected List applications = new ArrayList(); public CardEmul() { super(); } - protected abstract CardChannelEmul newCardChannel(CardEmul cardEmul); +// protected abstract CardChannelEmul newCardChannel(CardEmul cardEmul); @Override public void beginExclusive() throws CardException { @@ -71,9 +71,9 @@ public abstract class CardEmul extends Card { @Override public void disconnect(boolean reset) throws CardException { - if (reset) { - channel = newCardChannel(this); - } +// if (reset) { +// channel = newCardChannel(this); +// } } @Override @@ -93,7 +93,7 @@ public abstract class CardEmul extends Card { } public AbstractAppl getApplication(byte[] fid) { - + for(AbstractAppl appl : applications) { if (Arrays.equals(appl.getAID(), fid) || Arrays.equals(appl.getFID(), fid)) { return appl; diff --git a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java index b3bd07ab..44e48836 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java @@ -16,12 +16,14 @@ */ package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.CancelPINProvider; +import at.gv.egiz.smcc.pin.gui.InterruptPINProvider; +import at.gv.egiz.smcc.pin.gui.CancelChangePINProvider; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.List; @@ -32,119 +34,15 @@ import org.junit.Test; import at.gv.egiz.smcc.SignatureCard.KeyboxName; import at.gv.egiz.smcc.acos.A04ApplDEC; +import at.gv.egiz.smcc.pin.gui.DummyPINGUI; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; +import org.junit.Ignore; @SuppressWarnings("restriction") public abstract class CardTest { - public class TestPINProvider implements PINProvider { - - int provided = 0; - - char[] pin; - - public TestPINProvider(char[] pin) { - super(); - this.pin = pin; - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - provided++; - return pin; - } - - public int getProvided() { - return provided; - } - - } - - public class TestChangePINProvider extends TestPINProvider implements - ChangePINProvider { - - char[] oldPin; - - public TestChangePINProvider(char[] oldPin, char[] pin) { - super(pin); - this.oldPin = oldPin; - } - - @Override - public char[] provideOldPIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - return oldPin; - } - - } - - public class TestInvalidPINProvider implements PINProvider { - - int provided = 0; - int numWrongTries = 0; - - char[] pin; - - public TestInvalidPINProvider(char[] pin, int numWrongTries) { - super(); - this.pin = pin; - this.numWrongTries = numWrongTries; - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - if (provided >= numWrongTries) { - throw new CancelledException("Number of wrong tries reached: " + provided); - } else { - provided++; - return pin; - } - } - - public int getProvided() { - return provided; - } - } - - public class TestInvalidChangePINProvider implements ChangePINProvider { - - int provided = 0; - int numWrongTries = 0; - - char[] pin; - char[] oldPin; - - /** emulate ChangePinProvider */ - public TestInvalidChangePINProvider(char[] oldPin, char[] newPin, int numWrongTries) { - super(); - this.pin = newPin; - this.oldPin = oldPin; - this.numWrongTries = numWrongTries; - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - return pin; - } - - public int getProvided() { - return provided; - } - - @Override - public char[] provideOldPIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - if (provided >= numWrongTries) { - throw new CancelledException("Number of wrong tries reached: " + provided); - } else { - provided++; - return oldPin; - } - } - } - public CardTest() { super(); } @@ -167,7 +65,7 @@ public abstract class CardTest { SignatureCard signatureCard = createSignatureCard(); - TestPINProvider pinProvider = new TestPINProvider(pin); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider(pin); byte[] idlink = signatureCard.getInfobox("IdentityLink", pinProvider, null); @@ -184,13 +82,7 @@ public abstract class CardTest { SignatureCard signatureCard = createSignatureCard(); - PINProvider pinProvider = new PINProvider() { - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - throw new CancelledException(); - } - }; + PINGUI pinProvider = new CancelPINProvider(); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, pinProvider, @@ -205,13 +97,7 @@ public abstract class CardTest { SignatureCard signatureCard = createSignatureCard(); - PINProvider pinProvider = new PINProvider() { - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - throw new CancelledException(); - } - }; + PINGUI pinProvider = new CancelPINProvider(); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -226,13 +112,7 @@ public abstract class CardTest { SignatureCard signatureCard = createSignatureCard(); - PINProvider pinProvider = new PINProvider() { - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - throw new InterruptedException(); - } - }; + PINGUI pinProvider = new InterruptPINProvider(); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -247,13 +127,7 @@ public abstract class CardTest { SignatureCard signatureCard = createSignatureCard(); - PINProvider pinProvider = new PINProvider() { - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - throw new InterruptedException(); - } - }; + PINGUI pinProvider = new InterruptPINProvider(); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -268,11 +142,11 @@ public abstract class CardTest { final SignatureCard signatureCard = createSignatureCard(); - PINProvider pinProvider = new PINProvider() { + PINGUI pinProvider = new DummyPINGUI() { @Override public char[] providePIN(PINSpec spec, int retries) throws CancelledException, InterruptedException { - + try { signatureCard.getCertificate(KeyboxName.SECURE_SIGNATURE_KEYPAIR); assertTrue(false); @@ -281,10 +155,10 @@ public abstract class CardTest { // expected throw new CancelledException(); } - + } }; - + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, pinProvider, null); @@ -298,7 +172,7 @@ public abstract class CardTest { final SignatureCard signatureCard = createSignatureCard(); - PINProvider pinProvider = new PINProvider() { + PINGUI pinProvider = new DummyPINGUI() { @Override public char[] providePIN(PINSpec spec, int retries) throws CancelledException, InterruptedException { @@ -311,7 +185,6 @@ public abstract class CardTest { // expected throw new CancelledException(); } - } }; @@ -339,13 +212,7 @@ public abstract class CardTest { PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); - PINProvider pinProvider = new PINProvider() { - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - throw new CancelledException(); - } - }; + ModifyPINGUI pinProvider = new CancelChangePINProvider(); List specs = signatureCard.getPINSpecs(); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/PIN.java b/smcc/src/test/java/at/gv/egiz/smcc/PIN.java index ae883727..2cda0c2f 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/PIN.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/PIN.java @@ -23,19 +23,23 @@ public class PIN { public static final int STATE_PIN_VERIFIED = 1; public static final int STATE_PIN_BLOCKED = -1; + + public static final int STATE_PIN_NOTACTIVE = 2; public byte[] pin; public int kid; - public int state = STATE_RESET; + public int state; // = STATE_RESET; - public int kfpc = 10; + public int kfpc; // = 10; - public PIN(byte[] pin, int kid, int kfpc) { + //TODO also provde default constructor without state param + public PIN(byte[] pin, int kid, int kfpc, int state) { this.pin = pin; this.kid = kid; this.kfpc = kfpc; + this.state = state; } } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java index 9fd96d73..f4ac5c35 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java @@ -40,7 +40,7 @@ public class A03ApplDEC extends ACOSApplDEC { putFile(new File(FID_EF_INFOBOX, EF_INFOBOX, FCI_EF_INFOBOX, KID_PIN_INF)); try { - pins.put(KID_PIN_INF, new PIN("0000\0\0\0\0".getBytes("ASCII"), KID_PIN_INF, 10)); + pins.put(KID_PIN_INF, new PIN("0000\0\0\0\0".getBytes("ASCII"), KID_PIN_INF, 10, PIN.STATE_RESET)); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java index 58216b6b..7394bae7 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java @@ -24,13 +24,8 @@ import at.gv.egiz.smcc.CardEmul; public class A03CardEmul extends ACOSCardEmul { public A03CardEmul(A03ApplSIG applSIG, A03ApplDEC applDEC) { + channel = new A03CardChannelEmul(this); applications.add(applSIG); applications.add(applDEC); } - - @Override - protected CardChannelEmul newCardChannel(CardEmul cardEmul) { - return new A03CardChannelEmul(this); - } - } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java index 776c0370..3a8ac41c 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java @@ -22,15 +22,16 @@ import java.util.Arrays; import org.junit.Test; -import at.gv.egiz.smcc.ACOSCard; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.CardEmul; import at.gv.egiz.smcc.CardNotSupportedException; import at.gv.egiz.smcc.CardTerminalEmul; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; import at.gv.egiz.smcc.PINFormatException; import at.gv.egiz.smcc.PINMgmtSignatureCard; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; @@ -74,12 +75,12 @@ public class A03CardTest extends ACOSCardTest { char[] pin = defaultPin; for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { - signatureCard.verifyPIN(pinSpec, new TestPINProvider(pin)); + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); char[] newPin = new char[i]; Arrays.fill(newPin, '0'); signatureCard - .changePIN(pinSpec, new TestChangePINProvider(pin, newPin)); - signatureCard.verifyPIN(pinSpec, new TestPINProvider(newPin)); + .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin)); pin = newPin; } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java index 70925aa6..dd44d05b 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java @@ -24,14 +24,9 @@ import at.gv.egiz.smcc.CardEmul; public class A04CardEmul extends ACOSCardEmul { public A04CardEmul(A04ApplSIG applSIG, A04ApplDEC applDEC) { + channel = new A04CardChannelEmul(this); applications.add(applSIG); applications.add(applDEC); } - - @Override - protected CardChannelEmul newCardChannel(CardEmul cardEmul) { - return new A04CardChannelEmul(this); - } - } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java index d15e80d7..1cbea1b3 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java @@ -28,7 +28,6 @@ import java.util.Arrays; import org.junit.BeforeClass; import org.junit.Test; -import at.gv.egiz.smcc.ACOSCard; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.CardEmul; import at.gv.egiz.smcc.CardNotSupportedException; @@ -41,7 +40,8 @@ import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.SignatureCardFactory; -import at.gv.egiz.smcc.CardTest.TestPINProvider; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; public class A04CardTest extends ACOSCardTest { @@ -88,8 +88,8 @@ public class A04CardTest extends ACOSCardTest { char[] newPin = new char[i]; Arrays.fill(newPin, '0'); signatureCard - .changePIN(pinSpec, new TestChangePINProvider(pin, newPin)); - signatureCard.verifyPIN(pinSpec, new TestPINProvider(newPin)); + .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin)); pin = newPin; } @@ -111,7 +111,7 @@ public class A04CardTest extends ACOSCardTest { SignatureCard signatureCard = factory.createSignatureCard(card, new CardTerminalEmul(card)); - TestPINProvider pinProvider = new TestPINProvider(pin); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider(pin); byte[] idlink = signatureCard.getInfobox("IdentityLink", pinProvider, null); @@ -129,7 +129,7 @@ public class A04CardTest extends ACOSCardTest { SignatureCard signatureCard = createSignatureCard(); - TestPINProvider pinProvider = new TestPINProvider(pin); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider(pin); byte[] idlink = signatureCard.getInfobox("IdentityLink", pinProvider, null); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java index 08979536..09a754f3 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java @@ -297,7 +297,7 @@ public abstract class ACOSApplDEC extends ACOSAppl { System.arraycopy(C_CH_EKEY, 0, EF_C_CH_EKEY, 0, C_CH_EKEY.length); putFile(new File(FID_EF_C_CH_EKEY, EF_C_CH_EKEY, FCI_EF_C_CH_EKEY)); try { - pins.put(KID_PIN_DEC, new PIN("1234\0\0\0\0".getBytes("ASCII"), KID_PIN_DEC, 10)); + pins.put(KID_PIN_DEC, new PIN("1234\0\0\0\0".getBytes("ASCII"), KID_PIN_DEC, 10, PIN.STATE_RESET)); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java index e476b434..6ab5903a 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java @@ -221,7 +221,7 @@ public abstract class ACOSApplSIG extends ACOSAppl { // PINs try { - pins.put(KID_PIN_SIG, new PIN(Arrays.copyOf("123456".getBytes("ASCII"), 8), KID_PIN_SIG, 3)); + pins.put(KID_PIN_SIG, new PIN(Arrays.copyOf("123456".getBytes("ASCII"), 8), KID_PIN_SIG, 3, PIN.STATE_RESET)); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java index 56d1e4b2..4f012739 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java @@ -16,26 +16,23 @@ */ package at.gv.egiz.smcc.acos; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import org.junit.Test; -import at.gv.egiz.smcc.ACOSCard; import at.gv.egiz.smcc.CardEmul; import at.gv.egiz.smcc.CardNotSupportedException; import at.gv.egiz.smcc.CardTest; import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.SignatureCard.KeyboxName; @@ -60,7 +57,7 @@ public abstract class ACOSCardTest extends CardTest { appl.clearInfobox(); byte[] idlink = signatureCard.getInfobox("IdentityLink", - new TestPINProvider(pin), null); + new SMCCTestPINProvider(pin), null); assertNull(idlink); } @@ -76,7 +73,7 @@ public abstract class ACOSCardTest extends CardTest { ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC); appl.setInfoboxHeader((byte) 0xFF); - signatureCard.getInfobox("IdentityLink", new TestPINProvider(pin), null); + signatureCard.getInfobox("IdentityLink", new SMCCTestPINProvider(pin), null); } @@ -138,7 +135,7 @@ public abstract class ACOSCardTest extends CardTest { byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), - KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); + KeyboxName.SECURE_SIGNATURE_KEYPAIR, new SMCCTestPINProvider(pin), null); assertNotNull(signature); @@ -158,7 +155,7 @@ public abstract class ACOSCardTest extends CardTest { byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), - KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); + KeyboxName.CERITIFIED_KEYPAIR, new SMCCTestPINProvider(pin), null); assertNotNull(signature); @@ -171,7 +168,7 @@ public abstract class ACOSCardTest extends CardTest { SignatureCard signatureCard = createSignatureCard(); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray()); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -186,7 +183,7 @@ public abstract class ACOSCardTest extends CardTest { SignatureCard signatureCard = createSignatureCard(); - TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("0000".toCharArray()); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -204,7 +201,7 @@ public abstract class ACOSCardTest extends CardTest { ACOSApplSIG appl = (ACOSApplSIG) card.getApplication(ACOSAppl.AID_SIG); appl.setPin(ACOSApplSIG.KID_PIN_SIG, null); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray()); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -222,7 +219,7 @@ public abstract class ACOSCardTest extends CardTest { ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC); appl.setPin(ACOSApplDEC.KID_PIN_DEC, null); - TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("0000".toCharArray()); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java new file mode 100644 index 00000000..dffe7e29 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java @@ -0,0 +1,39 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class CancelChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { + + public CancelChangePINProvider() { + } + + @Override + public char[] provideCurrentPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + throw new CancelledException("cancelled by cancelPINProvider"); + } + + @Override + public char[] provideNewPIN(PINSpec spec) + throws CancelledException, InterruptedException { + throw new CancelledException("cancelled by cancelPINProvider"); + } + +} \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java new file mode 100644 index 00000000..77f19345 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class CancelPINProvider extends DummyPINGUI implements PINGUI { + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + throw new CancelledException("cancelled by cancelPINProvider"); + } +} \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java new file mode 100644 index 00000000..5eb8b9a1 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java @@ -0,0 +1,49 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class ChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { + + int provided = 0; + char[] pin; + char[] oldPin; + + public ChangePINProvider(char[] oldPin, char[] pin) { + this.pin = pin; + this.oldPin = oldPin; + } + + public int getProvided() { + return provided; + } + + @Override + public char[] provideCurrentPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + provided++; + return oldPin; + } + + @Override + public char[] provideNewPIN(PINSpec spec) { + return pin; + } + +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java new file mode 100644 index 00000000..fff89409 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java @@ -0,0 +1,68 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public abstract class DummyChangePINGUI implements ModifyPINGUI { + + @Override + public void validKeyPressed() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void correctionButtonPressed() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void allKeysCleared() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void finish() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void finishDirect() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void modifyPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void enterCurrentPIN(PINSpec spec, int retries) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void enterNewPIN(PINSpec spec) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void confirmNewPIN(PINSpec spec) { + throw new UnsupportedOperationException("Not supported yet."); + } +} \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java new file mode 100644 index 00000000..4d99b5c1 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public abstract class DummyPINGUI implements PINGUI { + + @Override + public void enterPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void enterPIN(PINSpec spec, int retries) throws CancelledException, InterruptedException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void validKeyPressed() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void correctionButtonPressed() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void allKeysCleared() { + throw new UnsupportedOperationException("Not supported yet."); + } +} \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java new file mode 100644 index 00000000..5706b888 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +@SuppressWarnings("restriction") +public class InterruptPINProvider extends DummyPINGUI implements PINGUI { + + public InterruptPINProvider() { + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + throw new InterruptedException("interrupted by cancelPINProvider"); + } + +} \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java new file mode 100644 index 00000000..69c9f42a --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class InvalidChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { + + int provided = 0; + int numWrongTries = 0; + char[] pin; + char[] oldPin; + + /** emulate ChangePinProvider */ + public InvalidChangePINProvider(char[] oldPin, char[] newPin, int numWrongTries) { + super(); + this.pin = newPin; + this.oldPin = oldPin; + this.numWrongTries = numWrongTries; + } + + @Override + public char[] provideCurrentPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (provided >= numWrongTries) { + throw new CancelledException("Number of wrong tries reached: " + provided); + } else { + provided++; + return oldPin; + } + } + + public int getProvided() { + return provided; + } + + @Override + public char[] provideNewPIN(PINSpec spec) { + return pin; + } +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java new file mode 100644 index 00000000..db01fd0d --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class InvalidPINProvider extends DummyPINGUI implements PINGUI { + + int provided = 0; + int numWrongTries = 0; + char[] pin; + + public InvalidPINProvider(char[] pin, int numWrongTries) { + super(); + this.pin = pin; + this.numWrongTries = numWrongTries; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (provided >= numWrongTries) { + throw new CancelledException("Number of wrong tries reached: " + provided); + } else { + provided++; + return pin; + } + } + + public int getProvided() { + return provided; + } +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java new file mode 100644 index 00000000..dffc90d7 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java @@ -0,0 +1,43 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class SMCCTestPINProvider extends DummyPINGUI implements PINGUI { + + public int provided = 0; + char[] pin; + + public SMCCTestPINProvider(char[] pin) { + this.pin = pin; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + provided++; + return pin; + } + + public int getProvided() { + return provided; + } + + +} \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java index 2ca63eea..62528e6e 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java @@ -69,27 +69,4 @@ public abstract class STARCOSAppl extends AbstractAppl implements CardAppl { pin.next().state = PIN.STATE_RESET; } } - - public void setPin(int kid, char[] value) { - PIN pin = pins.get(kid); - if (pin != null) { - if (value == null) { - pin.pin = null; - } else { - byte[] b = new byte[8]; - b[0] = (byte) (0x20 | value.length); - for(int i = 1, j = 0; i < b.length; i++) { - int h = ((j < value.length) - ? Character.digit(value[j++], 10) - : 0x0F); - int l = ((j < value.length) - ? Character.digit(value[j++], 10) - : 0x0F); - b[i] = (byte) ((h << 4) | l); - } - pin.pin = b; - } - } - } - } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java index cec305da..8741dd2d 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java @@ -16,7 +16,6 @@ */ package at.gv.egiz.smcc.starcos; -import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.Random; @@ -200,12 +199,18 @@ public class STARCOSApplGewoehnlicheSignatur extends STARCOSAppl { protected byte[] EF_C_X509_CH_AUT = new byte[2000]; - - public STARCOSApplGewoehnlicheSignatur(STARCOSCardChannelEmul channel) { + + protected byte[] dst; + + public static final byte[] DST = new byte[] { (byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x89, (byte) 0x03, (byte) 0x13, (byte) 0x35, (byte) 0x10}; + public static final byte[] DST_G3 = new byte[] { (byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x80, (byte) 0x01, (byte) 0x04 }; + + public STARCOSApplGewoehnlicheSignatur(STARCOSCardChannelEmul channel, byte[] dst) { super(channel); // Files System.arraycopy(C_X509_CH_AUT, 0, EF_C_X509_CH_AUT, 0, C_X509_CH_AUT.length); putFile(new File(FID_EF_C_X509_CH_AUT, EF_C_X509_CH_AUT, FCI_EF_C_X509_CH_AUT)); + this.dst = dst; } @Override @@ -240,12 +245,19 @@ public class STARCOSApplGewoehnlicheSignatur extends STARCOSAppl { case 0x81: // EXTERNAL AUTHENTICATE } + case 0xAA: + switch (command.getP1()) { + case 0x41: + if (Arrays.equals(new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x10}, command.getData())) { + return new ResponseAPDU(new byte[] {(byte) 0x90, (byte) 0x00}); + } + default: + return new ResponseAPDU(new byte[] {(byte) 0x6A, (byte) 0x80}); + } case 0xB6: switch (command.getP1()) { case 0x41: { // PSO - COMPUTE DIGITAL SIGNATURE - byte[] dst = new byte[] { (byte) 0x84, (byte) 0x03, (byte) 0x80, - (byte) 0x02, (byte) 0x00, (byte) 0x89, (byte) 0x03, (byte) 0x13, (byte) 0x35, (byte) 0x10}; if (Arrays.equals(dst, command.getData())) { securityEnv = command.getData(); return new ResponseAPDU(new byte[] {(byte) 0x90, (byte) 0x00}); @@ -328,5 +340,10 @@ public class STARCOSApplGewoehnlicheSignatur extends STARCOSAppl { } + @Override + public void setPin(int kid, char[] value) { + throw new UnsupportedOperationException("Not supported yet."); + } + } \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java index b7835a43..c470351a 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java @@ -156,5 +156,10 @@ public class STARCOSApplInfobox extends STARCOSAppl { throw new CardException("Not supported."); } + @Override + public void setPin(int kid, char[] value) { + throw new UnsupportedOperationException("Not supported yet."); + } + } \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java index 9fb5ad37..4036ca41 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java @@ -213,16 +213,14 @@ public class STARCOSApplSichereSignatur extends STARCOSAppl { protected byte[] EF_C_X509_CH_DS = new byte[2000]; - public STARCOSApplSichereSignatur(STARCOSCardChannelEmul channel) { + public STARCOSApplSichereSignatur(STARCOSCardChannelEmul channel, byte[] SS_pin, int pinState) { super(channel); // Files System.arraycopy(C_X509_CH_DS, 0, EF_C_X509_CH_DS, 0, C_X509_CH_DS.length); putFile(new File(FID_EF_C_X509_CH_DS, EF_C_X509_CH_DS, FCI_EF_C_X509_CH_DS)); // PINs - pins.put(KID_PIN_SS, new PIN(new byte[] { (byte) 0x24, (byte) 0x12, - (byte) 0x34, (byte) 0x56, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF }, KID_PIN_SS, 3)); + pins.put(KID_PIN_SS, new PIN(SS_pin, KID_PIN_SS, 3, pinState)); } @Override @@ -344,4 +342,34 @@ public class STARCOSApplSichereSignatur extends STARCOSAppl { } + /** + * set and activate pin + * @param value if null, pin will be set to NOTACTIVE + */ + @Override + public void setPin(int kid, char[] value) { + PIN pin = pins.get(kid); + if (pin != null) { + if (value == null) { +// pin.pin = null; + //TransportPIN +// pin.pin = new byte[] { (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + pin.state = PIN.STATE_PIN_NOTACTIVE; + } else { + byte[] b = new byte[8]; + b[0] = (byte) (0x20 | value.length); + for(int i = 1, j = 0; i < b.length; i++) { + int h = ((j < value.length) + ? Character.digit(value[j++], 10) + : 0x0F); + int l = ((j < value.length) + ? Character.digit(value[j++], 10) + : 0x0F); + b[i] = (byte) ((h << 4) | l); + } + pin.pin = b; + pin.state = PIN.STATE_RESET; + } + } + } } \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java index 89030894..2e0c54eb 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java @@ -16,7 +16,6 @@ */ package at.gv.egiz.smcc.starcos; -import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.HashMap; @@ -30,6 +29,8 @@ import at.gv.egiz.smcc.CardChannelEmul; import at.gv.egiz.smcc.CardEmul; import at.gv.egiz.smcc.File; import at.gv.egiz.smcc.PIN; +import java.util.ArrayList; +import java.util.List; @SuppressWarnings("restriction") public class STARCOSCardChannelEmul extends CardChannelEmul { @@ -40,14 +41,13 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { * */ protected CardEmul cardEmul; - + + public final List globalFiles = new ArrayList(); public final HashMap globalPins = new HashMap(); - public STARCOSCardChannelEmul(CardEmul cardEmul) { + public STARCOSCardChannelEmul(CardEmul cardEmul, byte[] Glob_PIN, int PIN_STATE) { this.cardEmul = cardEmul; - globalPins.put(KID_PIN_Glob, new PIN(new byte[] { (byte) 0x24, (byte) 0x00, - (byte) 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF }, KID_PIN_Glob, 10)); + globalPins.put(KID_PIN_Glob, new PIN(Glob_PIN, KID_PIN_Glob, 10, PIN_STATE)); } @Override @@ -88,6 +88,21 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { } } return new ResponseAPDU(new byte[] {(byte) 0x6A, (byte) 0x82}); + } else if (globalFiles != null) { + if (command.getP2() != 0x04) { + throw new CardException("Not supported."); + } + for (File file : globalFiles) { + if (Arrays.equals(fid, file.fid)) { + currentFile = file; + byte[] response = new byte[file.fcx.length + 2]; + System.arraycopy(file.fcx, 0, response, 0, file.fcx.length); + response[file.fcx.length] = (byte) 0x90; + response[file.fcx.length + 1] = (byte) 0x00; + return new ResponseAPDU(response); + } + } + return new ResponseAPDU(new byte[] {(byte) 0x6A, (byte) 0x82}); } else { throw new CardException("Not supported."); } @@ -121,6 +136,23 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { } + protected ResponseAPDU cmdREAD_RECORD(CommandAPDU command) throws CardException { + if (command.getINS() != 0xB2) { + throw new IllegalArgumentException("INS has to be 0xB2"); + } + if (currentFile == null) { + return new ResponseAPDU(new byte[]{ (byte) 0x69, (byte) 0x86 }); + } + if (command.getP1() != 0x01 || command.getP2() != 0x04) { + throw new CardException("Not implemented."); + } + byte[] response = new byte[currentFile.file.length + 2]; + System.arraycopy(currentFile.file, 0, response, 0, currentFile.file.length); + response[currentFile.file.length] = (byte) 0x90; + response[currentFile.file.length + 1] = (byte) 0x00; + return new ResponseAPDU(response); + } + protected ResponseAPDU cmdREAD_BINARY(CommandAPDU command) throws CardException { if (command.getINS() != 0xB0) { @@ -192,6 +224,10 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { case 0xB0: return cmdREAD_BINARY(command); + // READ RECORD + case 0xB2: + return cmdREAD_RECORD(command); + // VERIFY case 0x20: return cmdVERIFY(command); @@ -248,9 +284,15 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { } if (pin != null) { - - if (reference.length == 0) { - return new ResponseAPDU(new byte[] { (byte) 0x63, (byte) (pin.kfpc | 0xC0)}); + + if (reference == null || reference.length == 0) { + if (pin.state == PIN.STATE_PIN_NOTACTIVE) { + return new ResponseAPDU(new byte[] { (byte) 0x69, (byte) 0x84 }); + } else if (pin.state == PIN.STATE_PIN_BLOCKED) { + return new ResponseAPDU(new byte[] { (byte) 0x63, (byte) 0xc0 }); + } else { + return new ResponseAPDU(new byte[] { (byte) 0x63, (byte) (pin.kfpc | 0xC0)}); + } } if (reference.length != 8) { @@ -264,7 +306,7 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { case PIN.STATE_RESET: pin.state = PIN.STATE_PIN_VERIFIED; - + default: pin.kfpc = 10; return new ResponseAPDU(new byte[] { (byte) 0x90, (byte) 0x00 }); @@ -321,7 +363,20 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { return new ResponseAPDU(new byte[] {(byte) 0x67, (byte) 0x00}); } - response = verifyPin(0xFF & command.getP2(), data); + PIN pin; + if (currentAppl != null) { + pin = currentAppl.pins.get(command.getP2()); + } else { + pin = globalPins.get(command.getP2()); + } + if (pin.state == PIN.STATE_PIN_NOTACTIVE) { + pin.pin = data; + pin.state = PIN.STATE_RESET; + response = new ResponseAPDU(new byte[] { (byte) 0x90, (byte) 0x00 }); + } else { + // P1 == 0x01 not allowed on active pin (?) + response = new ResponseAPDU(new byte[] { (byte) 0x6A, (byte) 0x86}); + } } else if (command.getP1() == 0x00) { @@ -330,21 +385,22 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { } response = verifyPin(0xFF & command.getP2(), Arrays.copyOf(data, 8)); - + + if (response.getSW() == 0x9000) { + PIN pin; + if (currentAppl != null) { + pin = currentAppl.pins.get(command.getP2()); + } else { + pin = globalPins.get(command.getP2()); + } + pin.pin = Arrays.copyOfRange(data, 8, 16); + pin.state = PIN.STATE_PIN_VERIFIED; + } + } else { return new ResponseAPDU(new byte[] { (byte) 0x6A, (byte) 0x81 }); } - if (response.getSW() == 0x9000) { - PIN pin; - if (currentAppl != null) { - pin = currentAppl.pins.get(command.getP2()); - } else { - pin = globalPins.get(command.getP2()); - } - pin.pin = Arrays.copyOfRange(data, 8, 16); - } - return response; } @@ -353,7 +409,10 @@ public class STARCOSCardChannelEmul extends CardChannelEmul { PIN pin = globalPins.get(kid); if (pin != null) { if (value == null) { - pin.pin = null; +// pin.pin = null; + //TransportPIN +// pin.pin = new byte[] { (byte) 0x24, (byte) 0x12, (byte) 0x34, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + pin.state = PIN.STATE_PIN_NOTACTIVE; } else { byte[] b = new byte[8]; b[0] = (byte) (0x20 | value.length); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java index 7b2f3fbe..5963fb63 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java @@ -21,30 +21,34 @@ import javax.smartcardio.ATR; import at.gv.egiz.smcc.CardChannelEmul; import at.gv.egiz.smcc.CardEmul; +import at.gv.egiz.smcc.PIN; @SuppressWarnings("restriction") public class STARCOSCardEmul extends CardEmul { - + + public static byte[] DEFAULT_SS_PIN = new byte[] { (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + public static byte[] DEFAULT_Glob_PIN = new byte[] { (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + protected static ATR ATR = new ATR(new byte[] { (byte) 0x3b, (byte) 0xbd, (byte) 0x18, (byte) 0x00, (byte) 0x81, (byte) 0x31, (byte) 0xfe, (byte) 0x45, (byte) 0x80, (byte) 0x51, (byte) 0x02, (byte) 0x67, (byte) 0x05, (byte) 0x18, (byte) 0xb1, (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x81, (byte) 0x05, (byte) 0x31 }); - + public STARCOSCardEmul() { - applications.add(new STARCOSApplSichereSignatur((STARCOSCardChannelEmul) channel)); + this(DEFAULT_SS_PIN, DEFAULT_Glob_PIN, PIN.STATE_RESET); + } + + public STARCOSCardEmul(byte[] SS_PIN, byte[] Glob_PIN, int PIN_STATE) { + channel = new STARCOSCardChannelEmul(this, Glob_PIN, PIN_STATE); + applications.add(new STARCOSApplSichereSignatur((STARCOSCardChannelEmul) channel, SS_PIN, PIN_STATE)); applications.add(new STARCOSApplInfobox((STARCOSCardChannelEmul) channel)); - applications.add(new STARCOSApplGewoehnlicheSignatur((STARCOSCardChannelEmul) channel)); + applications.add(new STARCOSApplGewoehnlicheSignatur((STARCOSCardChannelEmul) channel, + STARCOSApplGewoehnlicheSignatur.DST)); } @Override public ATR getATR() { return ATR; } - - @Override - protected CardChannelEmul newCardChannel(CardEmul cardEmul) { - return new STARCOSCardChannelEmul(this); - } - } \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java index b7dc9a0c..154884d4 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java @@ -22,12 +22,9 @@ import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; -import javax.smartcardio.CardChannel; import org.junit.Test; @@ -36,25 +33,20 @@ import at.gv.egiz.smcc.CardEmul; import at.gv.egiz.smcc.CardNotSupportedException; import at.gv.egiz.smcc.CardTerminalEmul; import at.gv.egiz.smcc.CardTest; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; +import at.gv.egiz.smcc.pin.gui.InvalidChangePINProvider; +import at.gv.egiz.smcc.pin.gui.InvalidPINProvider; import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.PIN; import at.gv.egiz.smcc.PINFormatException; import at.gv.egiz.smcc.PINMgmtSignatureCard; import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.smcc.STARCOSCard; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.SignatureCardFactory; -import at.gv.egiz.smcc.CardTest.TestChangePINProvider; -import at.gv.egiz.smcc.CardTest.TestPINProvider; -import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; import at.gv.egiz.smcc.SignatureCard.KeyboxName; -import at.gv.egiz.smcc.acos.A03ApplDEC; -import at.gv.egiz.smcc.acos.A04ApplDEC; -import at.gv.egiz.smcc.acos.A04ApplSIG; -import at.gv.egiz.smcc.acos.ACOSAppl; -import at.gv.egiz.smcc.acos.ACOSApplDEC; -import at.gv.egiz.smcc.acos.ACOSApplSIG; import org.junit.Ignore; public class STARCOSCardTest extends CardTest { @@ -69,7 +61,17 @@ public class STARCOSCardTest extends CardTest { assertTrue(signatureCard instanceof PINMgmtSignatureCard); return signatureCard; } - + + protected SignatureCard createSignatureCard(byte[] SS_PIN, byte[] Glob_PIN, int pinState) + throws CardNotSupportedException { + SignatureCardFactory factory = SignatureCardFactory.getInstance(); + STARCOSCardEmul card = new STARCOSCardEmul(SS_PIN, Glob_PIN, pinState); + SignatureCard signatureCard = factory.createSignatureCard(card, + new CardTerminalEmul(card)); + assertTrue(signatureCard instanceof PINMgmtSignatureCard); + return signatureCard; + } + @Test public void testGetInfoboxIdentityLinkEmpty() throws SignatureCardException, InterruptedException, CardNotSupportedException { @@ -82,7 +84,7 @@ public class STARCOSCardTest extends CardTest { appl.clearInfobox(); byte[] idlink = signatureCard.getInfobox("IdentityLink", - new TestPINProvider(pin), null); + new SMCCTestPINProvider(pin), null); assertNull(idlink); } @@ -98,10 +100,10 @@ public class STARCOSCardTest extends CardTest { STARCOSApplInfobox appl = (STARCOSApplInfobox) card.getApplication(STARCOSAppl.AID_Infobox); appl.setInfoboxHeader((byte) 0xFF); - signatureCard.getInfobox("IdentityLink", new TestPINProvider(pin), null); + signatureCard.getInfobox("IdentityLink", new SMCCTestPINProvider(pin), null); } - + @Test public void testGetCerts() throws SignatureCardException, InterruptedException, CardNotSupportedException { @@ -145,7 +147,7 @@ public class STARCOSCardTest extends CardTest { signatureCard.getCertificate(KeyboxName.CERITIFIED_KEYPAIR); } - + @Test public void testSignSichereSignatur() throws SignatureCardException, InterruptedException, CardNotSupportedException, @@ -160,7 +162,7 @@ public class STARCOSCardTest extends CardTest { byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), - KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); + KeyboxName.SECURE_SIGNATURE_KEYPAIR, new SMCCTestPINProvider(pin), null); assertNotNull(signature); @@ -180,12 +182,12 @@ public class STARCOSCardTest extends CardTest { byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), - KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); + KeyboxName.CERITIFIED_KEYPAIR, new SMCCTestPINProvider(pin), null); assertNotNull(signature); } - + @Test(expected = LockedException.class) public void testSignSichereSignaturInvalidPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, @@ -193,7 +195,7 @@ public class STARCOSCardTest extends CardTest { SignatureCard signatureCard = createSignatureCard(); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray()); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -208,7 +210,7 @@ public class STARCOSCardTest extends CardTest { SignatureCard signatureCard = createSignatureCard(); - TestPINProvider pinProvider = new TestPINProvider("1234".toCharArray()); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("1234".toCharArray()); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -221,12 +223,9 @@ public class STARCOSCardTest extends CardTest { InterruptedException, CardNotSupportedException, NoSuchAlgorithmException, IOException { - SignatureCard signatureCard = createSignatureCard(); - CardEmul card = (CardEmul) signatureCard.getCard(); - STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); - appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, null); + SignatureCard signatureCard = createSignatureCard(null, null, PIN.STATE_PIN_BLOCKED); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray()); assertTrue(pinProvider.getProvided() <= 0); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" @@ -240,68 +239,79 @@ public class STARCOSCardTest extends CardTest { InterruptedException, CardNotSupportedException, NoSuchAlgorithmException, IOException { - SignatureCard signatureCard = createSignatureCard(); - CardEmul card = (CardEmul) signatureCard.getCard(); - STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); - channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, null); - - TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); + SignatureCard signatureCard = createSignatureCard(null, null, PIN.STATE_PIN_BLOCKED); + + SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("0000".toCharArray()); signatureCard.createSignature(new ByteArrayInputStream("MOCCA" .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, pinProvider, null); } - + @Test public void testChangePin() throws CardNotSupportedException, LockedException, NotActivatedException, CancelledException, PINFormatException, SignatureCardException, InterruptedException { - char[] defaultPin = "123456".toCharArray(); - - PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); - CardEmul card = (CardEmul) signatureCard.getCard(); - STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); - channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, defaultPin); - STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); - appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, defaultPin); + // set all initial pins to DEFAULT_SS_PIN (123456) + PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( + STARCOSCardEmul.DEFAULT_SS_PIN, STARCOSCardEmul.DEFAULT_SS_PIN, PIN.STATE_RESET); for (PINSpec pinSpec : signatureCard.getPINSpecs()) { - char[] pin = defaultPin; + char[] pin = "123456".toCharArray(); for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { - signatureCard.verifyPIN(pinSpec, new TestPINProvider(pin)); + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); char[] newPin = new char[i]; Arrays.fill(newPin, '0'); signatureCard - .changePIN(pinSpec, new TestChangePINProvider(pin, newPin)); - signatureCard.verifyPIN(pinSpec, new TestPINProvider(newPin)); + .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin)); pin = newPin; } } } @Test - public void testVerifyInvalidPin() throws CardNotSupportedException, + @Override + public void testActivatePin() throws CardNotSupportedException, LockedException, NotActivatedException, CancelledException, PINFormatException, SignatureCardException, InterruptedException { - char[] defaultPin = "123456".toCharArray(); + PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( + null, null, PIN.STATE_PIN_NOTACTIVE); + + for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + + char[] pin = "1234567890".substring(0, pinSpec.getMinLength()).toCharArray(); + + boolean notActive = false; + try { + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + } catch (NotActivatedException ex) { + notActive = true; + } + assertTrue(notActive); + + signatureCard.activatePIN(pinSpec, new ChangePINProvider(null, pin)); + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + } + } + + @Test + public void testVerifyInvalidPin() throws CardNotSupportedException, + LockedException, NotActivatedException, CancelledException, + PINFormatException, SignatureCardException, InterruptedException { PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); - CardEmul card = (CardEmul) signatureCard.getCard(); - STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); - channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, defaultPin); - STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); - appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, defaultPin); for (PINSpec pinSpec : signatureCard.getPINSpecs()) { char[] invalidPin = "999999".toCharArray(); int numInvalidTries = 2; - TestInvalidPINProvider invalidPinProvider = new TestInvalidPINProvider(invalidPin, numInvalidTries); + InvalidPINProvider invalidPinProvider = new InvalidPINProvider(invalidPin, numInvalidTries); try { signatureCard.verifyPIN(pinSpec, invalidPinProvider); } catch (CancelledException ex) { @@ -315,21 +325,15 @@ public class STARCOSCardTest extends CardTest { public void testChangeInvalidPin() throws CardNotSupportedException, LockedException, NotActivatedException, CancelledException, PINFormatException, SignatureCardException, InterruptedException { - char[] defaultPin = "123456".toCharArray(); PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); - CardEmul card = (CardEmul) signatureCard.getCard(); - STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); - channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, defaultPin); - STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); - appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, defaultPin); - + for (PINSpec pinSpec : signatureCard.getPINSpecs()) { char[] invalidPin = "999999".toCharArray(); int numInvalidTries = 2; - TestInvalidChangePINProvider invalidPinProvider = - new TestInvalidChangePINProvider(invalidPin, defaultPin, numInvalidTries); + InvalidChangePINProvider invalidPinProvider = + new InvalidChangePINProvider(invalidPin, invalidPin, numInvalidTries); try { signatureCard.changePIN(pinSpec, invalidPinProvider); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java new file mode 100644 index 00000000..dc6836ae --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java @@ -0,0 +1,46 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.starcos; + +import at.gv.egiz.smcc.CardEmul; +import at.gv.egiz.smcc.File; +import at.gv.egiz.smcc.PIN; + +/** + * + * @author clemens + */ +public class STARCOSG3CardChannelEmul extends STARCOSCardChannelEmul { + + public STARCOSG3CardChannelEmul(CardEmul cardEmul, byte[] Glob_PIN, int PIN_STATE) { + super(cardEmul, Glob_PIN, PIN_STATE); + + // G3 version file + byte[] versionFileFID = new byte[]{(byte) 0x00, (byte) 0x32}; + byte[] versionFile = new byte[]{ + (byte) 0xa5, (byte) 0x0e, (byte) 0x53, (byte) 0x02, (byte) 0x01, (byte) 0x20, (byte) 0x54, (byte) 0x08, + (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x04, (byte) 0x01, (byte) 0x70, (byte) 0x01}; + byte[] versionFileFCX = new byte[]{ + (byte) 0x62, (byte) 0x1a, (byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x14, (byte) 0x82, (byte) 0x05, + (byte) 0x44, (byte) 0x41, (byte) 0x00, (byte) 0x14, (byte) 0x01, (byte) 0x83, (byte) 0x02, (byte) 0x00, + (byte) 0x32, (byte) 0x88, (byte) 0x01, (byte) 0xd8, (byte) 0x8a, (byte) 0x01, (byte) 0x05, (byte) 0xa1, + (byte) 0x03, (byte) 0x8b, (byte) 0x01, (byte) 0x03}; + + globalFiles.add(new File(versionFileFID, versionFile, versionFileFCX)); + + } + } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java new file mode 100644 index 00000000..7583b3ad --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java @@ -0,0 +1,57 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.smcc.starcos; + +import at.gv.egiz.smcc.CardEmul; +import javax.smartcardio.ATR; + +import at.gv.egiz.smcc.PIN; + +@SuppressWarnings("restriction") +public class STARCOSG3CardEmul extends CardEmul { + + public static byte[] TRANSPORT_SS_PIN = new byte[] { (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + public static byte[] TRANSPORT_Glob_PIN = new byte[] { (byte) 0x24, (byte) 0x12, (byte) 0x34, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + + public static byte[] DEFAULT_SS_PIN = TRANSPORT_SS_PIN; + public static byte[] DEFAULT_Glob_PIN = new byte[] { (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + + protected static ATR ATR = new ATR(new byte[] { + (byte) 0x3b, (byte) 0xbd, (byte) 0x18, (byte) 0x00, (byte) 0x81, (byte) 0x31, (byte) 0xfe, (byte) 0x45, + (byte) 0x80, (byte) 0x51, (byte) 0x02, (byte) 0x67, (byte) 0x05, (byte) 0x18, (byte) 0xb1, (byte) 0x02, + (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x81, (byte) 0x05, (byte) 0x31 + }); + + public STARCOSG3CardEmul(byte[] SS_PIN, byte[] Glob_PIN, int PIN_STATE){ + channel = new STARCOSG3CardChannelEmul(this, Glob_PIN, PIN_STATE); + applications.add(new STARCOSApplSichereSignatur((STARCOSCardChannelEmul) channel, + SS_PIN, PIN_STATE)); + applications.add(new STARCOSApplInfobox((STARCOSCardChannelEmul) channel)); + applications.add(new STARCOSApplGewoehnlicheSignatur((STARCOSCardChannelEmul) channel, + STARCOSApplGewoehnlicheSignatur.DST_G3)); + } + + + public STARCOSG3CardEmul() { + this(DEFAULT_SS_PIN, DEFAULT_Glob_PIN, PIN.STATE_RESET); + } + + @Override + public ATR getATR() { + return ATR; + } +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java new file mode 100644 index 00000000..06744c82 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java @@ -0,0 +1,119 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* 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 at.gv.egiz.smcc.starcos; + +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + + +import org.junit.Test; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.CardEmul; +import at.gv.egiz.smcc.CardNotSupportedException; +import at.gv.egiz.smcc.CardTerminalEmul; +import at.gv.egiz.smcc.CardTest; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; +import at.gv.egiz.smcc.LockedException; +import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.PIN; +import at.gv.egiz.smcc.PINFormatException; +import at.gv.egiz.smcc.PINMgmtSignatureCard; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.SignatureCardFactory; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; +import org.junit.Ignore; + +public class STARCOSG3CardTest extends CardTest { + + @Override + protected SignatureCard createSignatureCard() + throws CardNotSupportedException { + SignatureCardFactory factory = SignatureCardFactory.getInstance(); + STARCOSG3CardEmul card = new STARCOSG3CardEmul(); + SignatureCard signatureCard = factory.createSignatureCard(card, + new CardTerminalEmul(card)); + assertTrue(signatureCard instanceof PINMgmtSignatureCard); + return signatureCard; + } + + protected SignatureCard createSignatureCard(byte[] SS_PIN, byte[] Glob_PIN, int pinState) + throws CardNotSupportedException { + SignatureCardFactory factory = SignatureCardFactory.getInstance(); + STARCOSG3CardEmul card = new STARCOSG3CardEmul(SS_PIN, Glob_PIN, pinState); + SignatureCard signatureCard = factory.createSignatureCard(card, + new CardTerminalEmul(card)); + assertTrue(signatureCard instanceof PINMgmtSignatureCard); + return signatureCard; + } + + @Test + public void testChangePin() throws CardNotSupportedException, + LockedException, NotActivatedException, CancelledException, + PINFormatException, SignatureCardException, InterruptedException { + + PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( + STARCOSG3CardEmul.DEFAULT_SS_PIN, STARCOSG3CardEmul.DEFAULT_SS_PIN, PIN.STATE_RESET); + + for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + + char[] pin = "123456".toCharArray(); + + for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + char[] newPin = new char[i]; + Arrays.fill(newPin, '0'); + signatureCard + .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin)); + pin = newPin; + } + } + } + + @Test + @Override + public void testActivatePin() throws CardNotSupportedException, + LockedException, NotActivatedException, CancelledException, + PINFormatException, SignatureCardException, InterruptedException { + + PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( + STARCOSG3CardEmul.TRANSPORT_SS_PIN, STARCOSG3CardEmul.TRANSPORT_SS_PIN, PIN.STATE_PIN_NOTACTIVE); + + for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + + char[] pin = "123456789".substring(0, pinSpec.getMinLength()).toCharArray(); + char[] transportPIN = "123456".toCharArray(); + + boolean notActive = false; + try { + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + } catch (NotActivatedException ex) { + notActive = true; + } + assertTrue(notActive); + + signatureCard.activatePIN(pinSpec, new ChangePINProvider(transportPIN, pin)); + signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); + } + } + + +} diff --git a/smccSTAL/src/main/java/META-INF/MANIFEST.MF b/smccSTAL/src/main/java/META-INF/MANIFEST.MF deleted file mode 100644 index 5e949512..00000000 --- a/smccSTAL/src/main/java/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java new file mode 100644 index 00000000..00738188 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.pin.gui; + +import at.gv.egiz.smcc.pin.gui.PINProvider; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * common super class providing action listener for all PIN GUIs + * @author Clemens Orthacker + */ +public abstract class AbstractPINProvider implements ActionListener { + + protected static final Log log = LogFactory.getLog(AbstractPINProvider.class); + + protected String action; + protected boolean actionPerformed; + + protected synchronized void waitForAction() throws InterruptedException { + try { + while (!actionPerformed) { + this.wait(); + } + } catch (InterruptedException e) { + log.error("[" + Thread.currentThread().getName() + "] interrupt in waitForAction"); + throw e; + } + actionPerformed = false; + } + + private synchronized void actionPerformed() { + actionPerformed = true; + notify();//All(); + } + + @Override + public void actionPerformed(ActionEvent e) { + log.debug("[" + Thread.currentThread().getName() + "] action performed - " + e.getActionCommand()); + action = e.getActionCommand(); + actionPerformed(); + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java new file mode 100644 index 00000000..81db0e90 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java @@ -0,0 +1,136 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.smccstal.SecureViewer; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.security.DigestException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * The number of retries is not fixed and there is no way (?) to obtain this value. + * A PINProvider should therefore maintain an internal retry counter or flag + * to decide whether or not to warn the user (num retries passed in providePIN). + * + * Therefore PINProvider objects should not be reused. + * + * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated) + * + * @author Clemens Orthacker + */ +public class SignPINGUI extends SignPINProvider implements PINGUI { + + protected static final Log log = LogFactory.getLog(SignPINGUI.class); + + private boolean retry = false; + + public SignPINGUI(BKUGUIFacade gui, SecureViewer viewer, SignedInfoType signedInfo) { + super(gui, viewer, signedInfo); + } + + @Override + public void enterPINDirect(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (retry) { + gui.showEnterPINDirect(spec, retries); + } else { + showSignatureData(spec); + gui.showEnterPINDirect(spec, -1); + retry = true; + } + } + + @Override + public void enterPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + if (retry) { + gui.showEnterPIN(spec, retries); + } else { + showSignatureData(spec); + gui.showEnterPIN(spec, -1); + retry = true; + } + } + + private void showSignatureData(PINSpec spec) + throws CancelledException, InterruptedException { + + gui.showSignatureDataDialog(spec, + this, "enterPIN", + this, "cancel", + this, "secureViewer"); + + do { + log.trace("[" + Thread.currentThread().getName() + "] wait for action"); + waitForAction(); + log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + + if ("secureViewer".equals(action)) { + try { + viewer.displayDataToBeSigned(signedInfo, this, "signatureData"); + } catch (DigestException ex) { + log.error("Bad digest value: " + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, + new Object[]{ex.getMessage()}, + this, "error"); + } catch (Exception ex) { + log.error("Could not display hashdata inputs: " + + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, + new Object[]{ex.getMessage()}, + this, "error"); + } + } else if ("signatureData".equals(action)) { + gui.showSignatureDataDialog(spec, + this, "enterPIN", + this, "cancel", + this, "secureViewer"); + } else if ("enterPIN".equals(action)) { + return; + } else if ("cancel".equals(action) || + "error".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } else { + log.error("unknown action command " + action); + } + } while (true); + } + + @Override + public void validKeyPressed() { + gui.validKeyPressed(); + } + + @Override + public void correctionButtonPressed() { + gui.correctionButtonPressed(); + } + + @Override + public void allKeysCleared() { + gui.allKeysCleared(); + } + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java new file mode 100644 index 00000000..fc1d39af --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java @@ -0,0 +1,105 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.smccstal.SecureViewer; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.PINProvider; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.security.DigestException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * The number of retries is not fixed and there is no way (?) to obtain this value. + * A PINProvider should therefore maintain an internal retry counter or flag + * to decide whether or not to warn the user (num retries passed in providePIN). + * + * Therefore PINProvider objects should not be reused. + * + * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated) + * + * @author Clemens Orthacker + */ +public class SignPINProvider extends AbstractPINProvider implements PINProvider { + + protected static final Log log = LogFactory.getLog(SignPINProvider.class); + + protected BKUGUIFacade gui; + protected SecureViewer viewer; + protected SignedInfoType signedInfo; + private boolean retry = false; + + public SignPINProvider(BKUGUIFacade gui, SecureViewer viewer, SignedInfoType signedInfo) { + this.gui = gui; + this.viewer = viewer; + this.signedInfo = signedInfo; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, + this, "sign", + this, "cancel", + this, "secureViewer"); + + do { + log.trace("[" + Thread.currentThread().getName() + "] wait for action"); + waitForAction(); + log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + + if ("secureViewer".equals(action)) { + try { + viewer.displayDataToBeSigned(signedInfo, this, "pinEntry"); + } catch (DigestException ex) { + log.error("Bad digest value: " + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, + new Object[]{ex.getMessage()}, + this, "error"); + } catch (Exception ex) { + log.error("Could not display hashdata inputs: " + + ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, + new Object[]{ex.getMessage()}, + this, "error"); + } + } else if ("sign".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + retry = true; + return gui.getPin(); + } else if ("pinEntry".equals(action)) { + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, + this, "sign", + this, "cancel", + this, "secureViewer"); + } else if ("cancel".equals(action) || + "error".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } else { + log.error("unknown action command " + action); + } + } while (true); + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java new file mode 100644 index 00000000..dc21492e --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * The number of retries is not fixed and there is no way (?) to obtain this value. + * A PINProvider should therefore maintain an internal retry counter or flag + * to decide whether or not to warn the user (num retries passed in providePIN). + * + * Therefore PINProvider objects should not be reused. + * + * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated) + * + * @author Clemens Orthacker + */ +public class VerifyPINGUI extends VerifyPINProvider implements PINGUI { + + protected static final Log log = LogFactory.getLog(VerifyPINGUI.class); + + private boolean retry = false; + + public VerifyPINGUI(BKUGUIFacade gui) { + super(gui); + } + + @Override + public void enterPINDirect(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + gui.showEnterPINDirect(spec, (retry) ? retries : -1); + retry = true; + } + + @Override + public void enterPIN(PINSpec spec, int retries) { + gui.showEnterPIN(spec, (retry) ? retries : -1); + retry = true; + } + + + @Override + public void validKeyPressed() { + gui.validKeyPressed(); + } + + @Override + public void correctionButtonPressed() { + gui.correctionButtonPressed(); + } + + @Override + public void allKeysCleared() { + gui.allKeysCleared(); + } + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java new file mode 100644 index 00000000..fda1e402 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java @@ -0,0 +1,72 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.PINProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * The number of retries is not fixed and there is no way (?) to obtain this value. + * A PINProvider should therefore maintain an internal retry counter or flag + * to decide whether or not to warn the user (num retries passed in providePIN). + * + * Therefore PINProvider objects should not be reused. + * + * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated) + * + * @author Clemens Orthacker + */ +public class VerifyPINProvider extends AbstractPINProvider implements PINProvider { + + protected static final Log log = LogFactory.getLog(VerifyPINProvider.class); + + protected BKUGUIFacade gui; + private boolean retry = false; + + public VerifyPINProvider(BKUGUIFacade gui) { + this.gui = gui; + } + + @Override + public char[] providePIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + gui.showVerifyPINDialog(spec, (retry) ? retries : -1, + this, "verify", + this, "cancel"); + + log.trace("[" + Thread.currentThread().getName() + "] wait for action"); + waitForAction(); + log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + + if ("cancel".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } + + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + retry = true; + return gui.getPin(); + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java deleted file mode 100644 index bc52c955..00000000 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractPINProvider.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * 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 at.gv.egiz.bku.smccstal; - -import at.gv.egiz.smcc.PINProvider; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author Clemens Orthacker - */ -public abstract class AbstractPINProvider implements PINProvider, ActionListener { - - protected static final Log log = LogFactory.getLog(AbstractPINProvider.class); - - protected boolean retry = false; - - protected String action; - - protected boolean actionPerformed; - -// protected void waitForAction() throws InterruptedException { -// super.wait(); -// } - - protected synchronized void waitForAction() throws InterruptedException { - try { - while (!actionPerformed) { - this.wait(); - } - } catch (InterruptedException e) { - log.error("[" + Thread.currentThread().getName() + "] interrupt in waitForAction"); - throw e; - } - actionPerformed = false; - } - - private synchronized void actionPerformed() { - actionPerformed = true; - notify();//All(); - } - - @Override - public void actionPerformed(ActionEvent e) { - log.debug("[" + Thread.currentThread().getName() + "] action performed - " + e.getActionCommand()); - action = e.getActionCommand(); - actionPerformed(); - } -} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java index 32e990c5..b34ab862 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java @@ -17,14 +17,13 @@ package at.gv.egiz.bku.smccstal; import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.pin.gui.VerifyPINGUI; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; import at.gv.egiz.smcc.SignatureCard; import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.stal.ErrorResponse; @@ -49,8 +48,7 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler { newSTALMessage("Message.RequestCaption", "Message.IdentityLink"); log.debug("Handling identitylink infobox"); byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), - new PINProviderFactory(card.getReader(), gui) - .getCardPINProvider(), + new VerifyPINGUI(gui), infoBox.getDomainIdentifier()); if (resp == null) { log.info("Infobox doesn't contain any data. Assume card is not activated."); @@ -97,8 +95,7 @@ public class InfoBoxReadRequestHandler extends AbstractRequestHandler { log.warn("Unknown infobox identifier: " + infoBox.getInfoboxIdentifier() + " trying generic request"); byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), - new PINProviderFactory(card.getReader(), gui) - .getCardPINProvider(), + new VerifyPINGUI(gui), infoBox.getDomainIdentifier()); if (resp == null) { return new ErrorResponse(6001); diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java deleted file mode 100644 index e5afe0ae..00000000 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/PINProviderFactory.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * 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 at.gv.egiz.bku.smccstal; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.stal.signedinfo.SignedInfoType; -import java.security.DigestException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * don't reuse the instance if the card reader might have changed! - * @author Clemens Orthacker - */ -public class PINProviderFactory { - - protected static final Log log = LogFactory.getLog(PINProviderFactory.class); - - protected CCID reader; - protected BKUGUIFacade gui; - - /** - * don't reuse the instance if the card reader might have changed! - * @param reader - * @param gui - */ - public PINProviderFactory(CCID reader, BKUGUIFacade gui) { - log.trace("PINProviderFactory for " + reader.getName()); - this.reader = reader; - this.gui = gui; - } - - - -// public static PINProviderFactory getInstance(SignatureCard forCard, -// BKUGUIFacade gui) { -// if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT) || -// forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { -// return new PinpadPINProviderFactory(gui); -// } else { -// return new SoftwarePINProviderFactory(gui); -// } -// } - - /** - * don't reuse the instance if the card reader might have changed! - * @param reader - * @param gui - * @return - */ -// public static PINProviderFactory getInstance(CCID reader, BKUGUIFacade gui) { -// log.trace("PINProviderFactory for " + reader.getName()); -// return new PINProviderFactory(reader, gui); -// } - - public PINProvider getSignaturePINProvider(SecureViewer viewer, - SignedInfoType signedInfo) { - if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START) || - reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { - log.debug("pinpad signature-pin provider"); - return new PinpadSignaturePinProvider(viewer, signedInfo); - } else { - log.debug("software signature-pin provider"); - return new SoftwareSignaturePinProvider(viewer, signedInfo); - } - } - - public PINProvider getCardPINProvider() { - if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START) || - reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { - log.debug("pinpad card-pin provider"); - return new PinpadCardPinProvider(); - } else { - log.debug("software card-pin provider"); - return new SoftwareCardPinProvider(); - } - } - - class SoftwareSignaturePinProvider extends AbstractPINProvider { - - protected SecureViewer viewer; - protected SignedInfoType signedInfo; - - private SoftwareSignaturePinProvider(SecureViewer viewer, - SignedInfoType signedInfo) { - this.viewer = viewer; - this.signedInfo = signedInfo; - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - gui.showSignaturePINDialog(spec, (retry) ? retries : -1, - this, "sign", - this, "cancel", - this, "secureViewer"); - - do { - log.debug("[" + Thread.currentThread().getName() + "] wait for action"); - waitForAction(); - log.debug("[" + Thread.currentThread().getName() + "] received action"); - - if ("secureViewer".equals(action)) { - try { - viewer.displayDataToBeSigned(signedInfo, this, "pinEntry"); - } catch (DigestException ex) { - log.error("Bad digest value: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, - new Object[]{ex.getMessage()}, - this, "error"); - } catch (Exception ex) { - log.error("Could not display hashdata inputs: " + - ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, - new Object[]{ex.getMessage()}, - this, "error"); - } - } else if ("sign".equals(action)) { - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - retry = true; - return gui.getPin(); - } else if ("pinEntry".equals(action)) { - gui.showSignaturePINDialog(spec, (retry) ? retries : -1, - this, "sign", - this, "cancel", - this, "secureViewer"); - } else if ("cancel".equals(action) || - "error".equals(action)) { - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - throw new CancelledException(spec.getLocalizedName() + - " entry cancelled"); - } else { - log.error("unknown action command " + action); - } - } while (true); - } - } - - class SoftwareCardPinProvider extends AbstractPINProvider { - - private SoftwareCardPinProvider() { - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - gui.showCardPINDialog(spec, (retry) ? retries : -1, - this, "ok", - this, "cancel"); - - log.debug("[" + Thread.currentThread().getName() + "] wait for action"); - waitForAction(); - - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - - if ("cancel".equals(action)) { - throw new CancelledException(spec.getLocalizedName() + - " entry cancelled"); - } - retry = true; - return gui.getPin(); - } - } - - class PinpadSignaturePinProvider extends AbstractPINProvider { - -// protected BKUGUIFacade gui; - protected SecureViewer viewer; - protected ViewerThread viewerThread; - protected SignedInfoType signedInfo; - - - private PinpadSignaturePinProvider(SecureViewer viewer, - SignedInfoType signedInfo) { - this.viewer = viewer; - this.signedInfo = signedInfo; - } - - protected class ViewerThread extends Thread { - - PINSpec pinSpec; - int retries; - - public ViewerThread(PINSpec pinSpec, int retries) { - this.pinSpec = pinSpec; - this.retries = retries; - } - - @Override - public void run() { - - try { - - gui.showPinpadSignaturePINDialog(pinSpec, retries, - PinpadSignaturePinProvider.this, "secureViewer"); - - while (true) { - log.debug("[" + Thread.currentThread().getName() + "] wait for action"); - waitForAction(); - log.debug("[" + Thread.currentThread().getName() + "] received action"); - - if ("secureViewer".equals(action)) { - viewer.displayDataToBeSigned(signedInfo, - PinpadSignaturePinProvider.this, "pinEntry"); - } else if ("pinEntry".equals(action)) { - gui.showPinpadSignaturePINDialog(pinSpec, retries, - PinpadSignaturePinProvider.this, "secureViewer"); - } else { - log.error("unsupported action command: " + action); - } - } - - } catch (DigestException ex) { - log.error("Bad digest value: " + ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, - new Object[]{ex.getMessage()}); - } catch (InterruptedException ex) { - log.info("pinpad secure viewer thread interrupted"); - } catch (Exception ex) { - log.error("Could not display hashdata inputs: " + - ex.getMessage()); - gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, - new Object[]{ex.getMessage()}); - } - } - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - if (viewerThread != null) { - updateViewerThread(retries); - } else { - viewerThread = new ViewerThread(spec, -1); - viewerThread.start(); - } -// if (viewerThread != null) { -// log.trace("interrupt old secure viewer thread"); -// viewerThread.interrupt(); -// } -// viewerThread = new ViewerThread(spec, (retry) ? retries : -1); -// log.trace("start new secure viewer thread"); -// viewerThread.start(); - - retry = true; - return null; - } - - private synchronized void updateViewerThread(int retries) { - log.trace("update viewer thread"); - viewerThread.retries = retries; - action = "pinEntry"; - actionPerformed = true; - notify(); - } - - -// @Override -// protected void finalize() throws Throwable { -// if (viewerThread != null) { -// viewerThread.interrupt(); -// } -// log.info("finalizing Pinpad SignaturePinProvider"); -// super.finalize(); -// } - } - - class PinpadCardPinProvider extends AbstractPINProvider { - - private PinpadCardPinProvider() { - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - showPinpadPINDialog(retries, spec); - retry = true; - return null; - - } - - private void showPinpadPINDialog(int retries, PINSpec pinSpec) { - String title, message; - Object[] params; - if (retry) { - title = BKUGUIFacade.TITLE_RETRY; - message = BKUGUIFacade.MESSAGE_RETRIES; - params = new Object[]{String.valueOf(retries)}; - } else { - title = BKUGUIFacade.TITLE_CARDPIN; - message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; - String pinSize = String.valueOf(pinSpec.getMinLength()); - if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { - pinSize += "-" + pinSpec.getMaxLength(); - } - params = new Object[]{pinSpec.getLocalizedName(), pinSize}; - } - gui.showMessageDialog(title, message, params); - } - } -} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 58d7b305..5b436d16 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -17,6 +17,7 @@ package at.gv.egiz.bku.smccstal; import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.pin.gui.SignPINGUI; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -78,8 +79,7 @@ public class SignRequestHandler extends AbstractRequestHandler { KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); byte[] resp = card.createSignature(new ByteArrayInputStream(signReq.getSignedInfo()), kb, - new PINProviderFactory(card.getReader(), gui) - .getSignaturePINProvider(secureViewer, si.getValue()), signatureMethod); + new SignPINGUI(gui, secureViewer, si.getValue()), signatureMethod); if (resp == null) { return new ErrorResponse(6001); } diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java index 16d3efa9..bf57b0a6 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -16,7 +16,7 @@ import org.junit.Test; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.smccstal.AbstractSMCCSTAL; import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler; -import at.gv.egiz.smcc.ccid.CCID; +import at.gv.egiz.smcc.pin.gui.PINGUI; import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.InfoboxReadRequest; import at.gv.egiz.stal.InfoboxReadResponse; @@ -39,7 +39,7 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements @Override public byte[] createSignature(InputStream input, KeyboxName keyboxName, - PINProvider provider, String alg) throws SignatureCardException { + PINGUI provider, String alg) throws SignatureCardException { // TODO Auto-generated method stub return null; } @@ -58,7 +58,7 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements } @Override - public byte[] getInfobox(String infobox, PINProvider provider, + public byte[] getInfobox(String infobox, PINGUI provider, String domainId) throws SignatureCardException { // TODO Auto-generated method stub return null; @@ -87,13 +87,6 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements // TODO Auto-generated method stub } - - @Override - public CCID getReader() { - // TODO Auto-generated method stub - return null; - } - }; return false; } diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINGUI.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINGUI.java new file mode 100644 index 00000000..26a24609 --- /dev/null +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINGUI.java @@ -0,0 +1,88 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade.DIALOG; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class ManagementPINGUI extends ManagementPINProvider implements ModifyPINGUI { + + protected static final Log log = LogFactory.getLog(ManagementPINGUI.class); + + private boolean retry = false; + + public ManagementPINGUI(PINManagementGUIFacade gui, DIALOG type) { + super(gui, type); + } + + @Override + public void modifyPINDirect(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + gui.showModifyPINDirect(type, spec, (retry) ? retries : -1); + retry = true; + } + + @Override + public void finishDirect() { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, BKUGUIFacade.MESSAGE_WAIT); + } + + @Override + public void enterCurrentPIN(PINSpec spec, int retries) { + gui.showEnterCurrentPIN(type, spec, (retry) ? retries : -1); + retry = true; + } + + @Override + public void enterNewPIN(PINSpec spec) { + gui.showEnterNewPIN(type, spec); + retry = true; + } + + @Override + public void confirmNewPIN(PINSpec spec) { + gui.showConfirmNewPIN(type, spec); + retry = true; + } + + + @Override + public void validKeyPressed() { + gui.validKeyPressed(); + } + + @Override + public void correctionButtonPressed() { + gui.correctionButtonPressed(); + } + + @Override + public void allKeysCleared() { + gui.allKeysCleared(); + } + + @Override + public void finish() { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, BKUGUIFacade.MESSAGE_WAIT); + } +} diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINProvider.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINProvider.java new file mode 100644 index 00000000..8d842d13 --- /dev/null +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/pin/gui/ManagementPINProvider.java @@ -0,0 +1,89 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.egiz.bku.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class ManagementPINProvider extends AbstractPINProvider implements ModifyPINProvider { + + protected static final Log log = LogFactory.getLog(ManagementPINProvider.class); + protected PINManagementGUIFacade gui; + protected PINManagementGUIFacade.DIALOG type; + private boolean retry = false; + + public ManagementPINProvider(PINManagementGUIFacade gui, PINManagementGUIFacade.DIALOG type) { + this.gui = gui; + this.type = type; + } + + @Override + public char[] provideCurrentPIN(PINSpec spec, int retries) + throws CancelledException, InterruptedException { + + gui.showPINDialog(type, spec, (retry) ? retries : -1, + this, "change", + this, "cancel"); + + log.trace("[" + Thread.currentThread().getName() + "] wait for action"); + waitForAction(); + log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + + if ("cancel".equals(action)) { + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } + retry = true; + return gui.getOldPin(); + } + + @Override + public char[] provideNewPIN(PINSpec spec) + throws CancelledException, InterruptedException { + + char[] pin = gui.getPin(); + if (pin != null) { + // change pin dialog also returns new pin + return pin; + } + + gui.showPINDialog(type, spec, -1, + this, "activate", + this, "cancel"); + + log.trace("[" + Thread.currentThread().getName() + "] wait for action"); + waitForAction(); + log.trace("[" + Thread.currentThread().getName() + "] received action " + action); + + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, + BKUGUIFacade.MESSAGE_WAIT); + + if ("cancel".equals(action)) { + throw new CancelledException(spec.getLocalizedName() + + " entry cancelled"); + } + return gui.getPin(); + } +} diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java deleted file mode 100644 index 493733b8..00000000 --- a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * 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 at.gv.egiz.bku.smccstal; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.ChangePINProvider; -import at.gv.egiz.bku.gui.PINManagementGUIFacade; -import at.gv.egiz.bku.smccstal.AbstractPINProvider; -import at.gv.egiz.bku.smccstal.PINProviderFactory; -import at.gv.egiz.smcc.CancelledException; -import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.PINProvider; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.smcc.SignatureCard; - -/** - * - * @author Clemens Orthacker - */ -public class ManagementPINProviderFactory extends PINProviderFactory { - - public ManagementPINProviderFactory(CCID reader, PINManagementGUIFacade gui) { - super(reader, gui); - } - -// public static ManagementPINProviderFactory getInstance(SignatureCard forCard, -// PINManagementGUIFacade gui) { -// if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { -// return new PinpadPINProviderFactory(gui); -// -// } else { -// return new SoftwarePINProviderFactory(gui); -// } -// } - - public PINProvider getVerifyPINProvider() { - if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { - return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); - } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { - return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); - } else { - return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.VERIFY); - } - } - - public PINProvider getActivatePINProvider() { - if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { - return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); - } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { - return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); - } else { - return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.ACTIVATE); - } - } - - public ChangePINProvider getChangePINProvider() { - if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_START)) { - return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.CHANGE); - } else if (reader.hasFeature(CCID.FEATURE_MODIFY_PIN_DIRECT)) { - return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.CHANGE); - } else { - return new ChangePinProvider(); - } - } - - public PINProvider getUnblockPINProvider() { - if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_START)) { - return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); - } else if (reader.hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { - return new PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); - } else { - return new SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG.UNBLOCK); - } - } - - class PinpadGenericPinProvider extends AbstractPINProvider - implements ChangePINProvider { - - protected PINManagementGUIFacade.DIALOG type; - - private PinpadGenericPinProvider(PINManagementGUIFacade.DIALOG type) { - this.type = type; - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - showPinpadPINDialog(retries, spec); - retry = true; - return null; - } - - /** - * do not call this method without calling providePIN() - * (no message is displayed) - * @param spec - * @param retries - * @return - */ - @Override - public char[] provideOldPIN(PINSpec spec, int retries) { - return null; - } - - private void showPinpadPINDialog(int retries, PINSpec pinSpec) { - String title, message; - Object[] params; - if (retry) { - if (retries == 1) { - message = BKUGUIFacade.MESSAGE_LAST_RETRY_PINPAD; - } else { - message = BKUGUIFacade.MESSAGE_RETRIES_PINPAD; - } - title = BKUGUIFacade.TITLE_RETRY; - params = new Object[]{String.valueOf(retries)}; - } else if (type == PINManagementGUIFacade.DIALOG.VERIFY) { - title = PINManagementGUIFacade.TITLE_VERIFY_PIN; - message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; - params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; - } else if (type == PINManagementGUIFacade.DIALOG.ACTIVATE) { - title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; - message = PINManagementGUIFacade.MESSAGE_ACTIVATEPIN_PINPAD; - params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; - } else if (type == PINManagementGUIFacade.DIALOG.CHANGE) { - title = PINManagementGUIFacade.TITLE_CHANGE_PIN; - message = PINManagementGUIFacade.MESSAGE_CHANGEPIN_PINPAD; - params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; - } else { //if (type == DIALOG.UNBLOCK) { - title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; - message = PINManagementGUIFacade.MESSAGE_UNBLOCKPIN_PINPAD; - params = new Object[]{pinSpec.getLocalizedName(), pinSpec.getLocalizedLength()}; - } - gui.showMessageDialog(title, message, params); - } - } - - - class SoftwareGenericPinProvider extends AbstractPINProvider { - -// protected PINManagementGUIFacade gui; - protected PINManagementGUIFacade.DIALOG type; - - private SoftwareGenericPinProvider(PINManagementGUIFacade.DIALOG type) { - this.type = type; - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - - ((PINManagementGUIFacade) gui).showPINDialog(type, spec, - (retry) ? retries : -1, - this, "exec", - this, "back"); - - waitForAction(); - - if ("exec".equals(action)) { - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - retry = true; - return gui.getPin(); - } else if ("back".equals(action)) { - throw new CancelledException(); - } else { - log.error("unsupported command " + action); - throw new CancelledException(); - } - } - } - - class ChangePinProvider extends AbstractPINProvider - implements ChangePINProvider { - -// protected PINManagementGUIFacade gui; - - private char[] oldPin; - private char[] newPin; - - private ChangePinProvider() { - } - - @Override - public char[] providePIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - if (newPin == null) { - getPINs(spec, retries); - } - char[] pin = newPin; - newPin = null; - return pin; - } - - @Override - public char[] provideOldPIN(PINSpec spec, int retries) - throws CancelledException, InterruptedException { - if (oldPin == null) { - getPINs(spec, retries); - } - char[] pin = oldPin; - oldPin = null; - return pin; - } - - private void getPINs(PINSpec spec, int retries) - throws InterruptedException, CancelledException { - - ((PINManagementGUIFacade) gui).showPINDialog( - PINManagementGUIFacade.DIALOG.CHANGE, spec, - (retry) ? retries : -1, - this, "exec", - this, "back"); - - waitForAction(); - - if ("exec".equals(action)) { - gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, - BKUGUIFacade.MESSAGE_WAIT); - retry = true; - oldPin = ((PINManagementGUIFacade) gui).getOldPin(); - newPin = gui.getPin(); - } else if ("back".equals(action)) { - throw new CancelledException(); - } else { - log.error("unsupported command " + action); - throw new CancelledException(); - } - } - } -} diff --git a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java index bfeb90b0..0d49afd0 100644 --- a/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java +++ b/smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java @@ -23,9 +23,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUI; import at.gv.egiz.bku.gui.PINManagementGUIFacade; import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; -import at.gv.egiz.bku.smccstal.AbstractRequestHandler; +import at.gv.egiz.bku.pin.gui.ManagementPINGUI; +import at.gv.egiz.bku.pin.gui.VerifyPINGUI; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.LockedException; import at.gv.egiz.smcc.NotActivatedException; @@ -96,40 +98,15 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { throw new NullPointerException("no PIN selected for activation/change"); } - ManagementPINProviderFactory ppfac = - new ManagementPINProviderFactory(card.getReader(), gui); - try { if ("activate_enterpin".equals(actionCommand)) { - log.info("activate " + selectedPIN.getLocalizedName()); - ((PINMgmtSignatureCard) card).activatePIN(selectedPIN, - ppfac.getActivatePINProvider()); - updatePINState(selectedPIN, STATUS.ACTIV); - gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, - PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, - new Object[] {selectedPIN.getLocalizedName()}, - BKUGUIFacade.BUTTON_OK, this, "ok"); - waitForAction(); + activatePIN(selectedPIN); } else if ("change_enterpin".equals(actionCommand)) { - log.info("change " + selectedPIN.getLocalizedName()); - ((PINMgmtSignatureCard) card).changePIN(selectedPIN, - ppfac.getChangePINProvider()); - updatePINState(selectedPIN, STATUS.ACTIV); - gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, - PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, - new Object[] {selectedPIN.getLocalizedName()}, - BKUGUIFacade.BUTTON_OK, this, "ok"); - waitForAction(); - + changePIN(selectedPIN); } else if ("unblock_enterpuk".equals(actionCommand)) { - log.info("unblock " + selectedPIN.getLocalizedName()); - ((PINMgmtSignatureCard) card).unblockPIN(selectedPIN, - ppfac.getUnblockPINProvider()); + unblockPIN(selectedPIN); } else if ("verify_enterpin".equals(actionCommand)) { - log.info("verify " + selectedPIN.getLocalizedName()); - ((PINMgmtSignatureCard) card).verifyPIN(selectedPIN, - ppfac.getVerifyPINProvider()); - updatePINState(selectedPIN, STATUS.ACTIV); + verifyPIN(selectedPIN); } } catch (CancelledException ex) { log.trace("cancelled"); @@ -154,29 +131,17 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { new Object[] {selectedPIN.getLocalizedName()}, this, null); waitForAction(); - } catch (PINConfirmationException ex) { - log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); - gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, - new Object[] {selectedPIN.getLocalizedName()}, - this, null); - waitForAction(); + + // inner loop for pinConfirmation and pinFormat ex +// } catch (PINConfirmationException ex) { +// } catch (PINFormatException ex) { + } catch (PINOperationAbortedException ex) { log.error("pin operation aborted without further details"); gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_OPERATION_ABORTED, new Object[] {selectedPIN.getLocalizedName()}, this, null); waitForAction(); - } catch (PINFormatException ex) { - log.error("wrong format of new " + selectedPIN.getLocalizedName()); -// updatePINStatus(selectedPIN, STATUS.NOT_ACTIV); - String pinSize = String.valueOf(selectedPIN.getMinLength()); - if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { - pinSize += "-" + selectedPIN.getMaxLength(); - } - gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, - new Object[] {selectedPIN.getLocalizedName(), pinSize}, - this, null); - waitForAction(); } } // end if @@ -206,6 +171,157 @@ public class PINManagementRequestHandler extends AbstractRequestHandler { } } + private void activatePIN(PINSpec selectedPIN) + throws InterruptedException, SignatureCardException, GetPINStatusException { + + log.info("activate " + selectedPIN.getLocalizedName()); + ManagementPINGUI pinGUI = new ManagementPINGUI((PINManagementGUI) gui, + PINManagementGUIFacade.DIALOG.ACTIVATE); + + boolean reentry; + do { + try { + reentry = false; + ((PINMgmtSignatureCard) card).activatePIN(selectedPIN, pinGUI); + } catch (PINConfirmationException ex) { + reentry = true; + log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (PINFormatException ex) { + reentry = true; + log.error("wrong format of new " + selectedPIN.getLocalizedName()); + String pinSize = String.valueOf(selectedPIN.getMinLength()); + if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { + pinSize += "-" + selectedPIN.getMaxLength(); + } + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, + new Object[] {selectedPIN.getLocalizedName(), pinSize}, + this, null); + waitForAction(); + } + } while (reentry); + + updatePINState(selectedPIN, STATUS.ACTIV); + gui.showMessageDialog(PINManagementGUIFacade.TITLE_ACTIVATE_SUCCESS, + PINManagementGUIFacade.MESSAGE_ACTIVATE_SUCCESS, + new Object[]{selectedPIN.getLocalizedName()}, + BKUGUIFacade.BUTTON_OK, this, "ok"); + waitForAction(); + } + + private void verifyPIN(PINSpec selectedPIN) + throws InterruptedException, SignatureCardException, GetPINStatusException { + + log.info("verify " + selectedPIN.getLocalizedName()); + VerifyPINGUI pinGUI = new VerifyPINGUI(gui); + + boolean reentry; + do { + try { + reentry = false; + ((PINMgmtSignatureCard) card).verifyPIN(selectedPIN, pinGUI); + } catch (PINFormatException ex) { + reentry = true; + log.error("wrong format of new " + selectedPIN.getLocalizedName()); + String pinSize = String.valueOf(selectedPIN.getMinLength()); + if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { + pinSize += "-" + selectedPIN.getMaxLength(); + } + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, + new Object[] {selectedPIN.getLocalizedName(), pinSize}, + this, null); + waitForAction(); + } + } while (reentry); + + updatePINState(selectedPIN, STATUS.ACTIV); + } + + private void changePIN(PINSpec selectedPIN) + throws SignatureCardException, GetPINStatusException, InterruptedException { + + log.info("change " + selectedPIN.getLocalizedName()); + ManagementPINGUI pinGUI = new ManagementPINGUI((PINManagementGUI) gui, + PINManagementGUIFacade.DIALOG.CHANGE); + + boolean reentry; + do { + try { + reentry = false; + ((PINMgmtSignatureCard) card).changePIN(selectedPIN, pinGUI); + } catch (PINConfirmationException ex) { + reentry = true; + log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (PINFormatException ex) { + reentry = true; + log.error("wrong format of new " + selectedPIN.getLocalizedName()); + String pinSize = String.valueOf(selectedPIN.getMinLength()); + if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { + pinSize += "-" + selectedPIN.getMaxLength(); + } + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, + new Object[] {selectedPIN.getLocalizedName(), pinSize}, + this, null); + waitForAction(); + } + } while (reentry); + + updatePINState(selectedPIN, STATUS.ACTIV); + gui.showMessageDialog(PINManagementGUIFacade.TITLE_CHANGE_SUCCESS, + PINManagementGUIFacade.MESSAGE_CHANGE_SUCCESS, + new Object[]{selectedPIN.getLocalizedName()}, + BKUGUIFacade.BUTTON_OK, this, "ok"); + waitForAction(); + } + + private void unblockPIN(PINSpec selectedPIN) + throws SignatureCardException, GetPINStatusException, InterruptedException { + + log.info("unblock " + selectedPIN.getLocalizedName()); + ManagementPINGUI pinGUI = new ManagementPINGUI((PINManagementGUI) gui, + PINManagementGUIFacade.DIALOG.UNBLOCK); + + boolean reentry; + do { + try { + reentry = false; + ((PINMgmtSignatureCard) card).unblockPIN(selectedPIN, pinGUI); + } catch (PINConfirmationException ex) { + reentry = true; + log.error("confirmation pin does not match new " + selectedPIN.getLocalizedName()); + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_CONFIRMATION, + new Object[] {selectedPIN.getLocalizedName()}, + this, null); + waitForAction(); + } catch (PINFormatException ex) { + reentry = true; + log.error("wrong format of new " + selectedPIN.getLocalizedName()); + String pinSize = String.valueOf(selectedPIN.getMinLength()); + if (selectedPIN.getMinLength() != selectedPIN.getMaxLength()) { + pinSize += "-" + selectedPIN.getMaxLength(); + } + gui.showErrorDialog(PINManagementGUIFacade.ERR_PIN_FORMAT, + new Object[] {selectedPIN.getLocalizedName(), pinSize}, + this, null); + waitForAction(); + } + } while (reentry); + + updatePINState(selectedPIN, STATUS.ACTIV); + gui.showMessageDialog(PINManagementGUIFacade.TITLE_UNBLOCK_SUCCESS, + PINManagementGUIFacade.MESSAGE_UNBLOCK_SUCCESS, + new Object[]{selectedPIN.getLocalizedName()}, + BKUGUIFacade.BUTTON_OK, this, "ok"); + waitForAction(); + } + @Override public boolean requireCard() { return true; -- cgit v1.2.3