From f3ba184673d938677696a3cb7c8e620822aef181 Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 28 Jan 2009 19:40:53 +0000 Subject: activation git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@292 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- BKUAppletExt/src/test/resources/appletTest.html | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 BKUAppletExt/src/test/resources/appletTest.html (limited to 'BKUAppletExt/src/test') diff --git a/BKUAppletExt/src/test/resources/appletTest.html b/BKUAppletExt/src/test/resources/appletTest.html new file mode 100644 index 00000000..f7a47d0a --- /dev/null +++ b/BKUAppletExt/src/test/resources/appletTest.html @@ -0,0 +1,34 @@ + + + +
+ + + + + + + + + + +
+ + \ No newline at end of file -- cgit v1.2.3 From d7fde6fc92f36a7cc8b8d412724951b12193bb9b Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 11 Feb 2009 20:01:17 +0000 Subject: activation applet (NO PINMgmt yet) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@295 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- BKUAppletExt/nbactions.xml | 13 + .../java/at/gv/egiz/bku/gui/ActivationGUI.java | 249 ++++++++++++ .../at/gv/egiz/bku/gui/ActivationGUIFacade.java | 33 ++ .../main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java | 52 +++ .../java/at/gv/egiz/bku/gui/PINManagementGUI.java | 159 ++++++++ .../at/gv/egiz/bku/gui/PINManagementGUIFacade.java | 34 ++ .../java/at/gv/egiz/bku/gui/PINStatusProvider.java | 32 ++ .../egiz/bku/online/applet/ActivationApplet.java | 90 +++++ .../bku/online/applet/PINManagementApplet.java | 50 +++ .../bku/online/applet/PINManagementBKUWorker.java | 112 ++++++ .../egiz/bku/online/applet/ext/BKUAppletExt.java | 80 ---- .../bku/smccstal/ext/CardMgmtRequestHandler.java | 48 ++- .../bku/smccstal/ext/PINMgmtRequestHandler.java | 93 +++++ .../gv/egiz/bku/gui/ActivationMessages.properties | 24 ++ .../egiz/bku/gui/ActivationMessages_en.properties | 24 ++ .../java/at/gv/egiz/bku/gui/ActivationGuiTest.java | 62 +++ .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 204 ++++++++++ .../gv/egiz/bku/smccstal/ext/FileSystemTest.java | 434 +++++++++++++++++++++ BKUAppletExt/src/test/resources/appletTest.html | 4 +- 19 files changed, 1704 insertions(+), 93 deletions(-) create mode 100644 BKUAppletExt/nbactions.xml create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ActivationApplet.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ext/BKUAppletExt.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java create mode 100644 BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties create mode 100644 BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties create mode 100644 BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java create mode 100644 BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java create mode 100644 BKUAppletExt/src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java (limited to 'BKUAppletExt/src/test') diff --git a/BKUAppletExt/nbactions.xml b/BKUAppletExt/nbactions.xml new file mode 100644 index 00000000..286e3ba6 --- /dev/null +++ b/BKUAppletExt/nbactions.xml @@ -0,0 +1,13 @@ + + + + CUSTOM-PackageNoTests + PackageNoTests + + package + + + true + + + diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java new file mode 100644 index 00000000..8134ac5f --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java @@ -0,0 +1,249 @@ +/* + * 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.awt.Container; +import java.awt.Cursor; +import java.awt.event.ActionListener; +import java.net.URL; +import java.text.MessageFormat; +import java.util.Locale; +import java.util.ResourceBundle; +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JProgressBar; +import javax.swing.LayoutStyle; +import javax.swing.SwingUtilities; + +/** + * + * @author Clemens Orthacker + */ +public class ActivationGUI extends CardMgmtGUI implements ActivationGUIFacade { + + public static final String TITLE_ACTIVATION = "title.activation"; + public static final String LABEL_ACTIVATION = "label.activation"; + public static final String LABEL_ACTIVATION_STEP = "label.activation.step"; + public static final String LABEL_ACTIVATION_IDLE = "label.activation.idle"; + + public static final String HELP_ACTIVATION = "help.activation"; + + protected JProgressBar progressBar; + + public ActivationGUI(Container contentPane, + Locale locale, + Style guiStyle, + URL backgroundImgURL, + AbstractHelpListener helpListener) { + super(contentPane, locale, guiStyle, backgroundImgURL, helpListener); + + progressBar = new JProgressBar(); + } + + @Override + public void showActivationProgressDialog(final int currentStep, final int maxProgress, final ActionListener cancelListener, final String cancelCommand) { + + log.debug("scheduling activation progress dialog (step " + currentStep + ")"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("show activation progress dialog (step " + currentStep + ")"); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + mainPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + + JLabel infoLabel = new JLabel(); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + + if (renderHeaderPanel) { + titleLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); + infoLabel.setText(cardmgmtMessages.getString(LABEL_ACTIVATION)); + } else { + infoLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); + } + + helpListener.setHelpTopic(HELP_ACTIVATION); + + progressBar.setIndeterminate(false); + progressBar.setStringPainted(true); + progressBar.setString(null); //reset to percentage + progressBar.setMinimum(0); + progressBar.setMaximum(maxProgress); + + JLabel stepLabel = new JLabel(); + stepLabel.setFont(stepLabel.getFont().deriveFont(stepLabel.getFont().getStyle() & ~java.awt.Font.BOLD, stepLabel.getFont().getSize()-2)); + String stepPattern = cardmgmtMessages.getString(LABEL_ACTIVATION_STEP); + stepLabel.setText(MessageFormat.format(stepPattern, new Object[]{ currentStep })); + + 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) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(stepLabel) + .addComponent(progressBar))); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(infoVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(stepLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(progressBar))); + + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + 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(); + + } + }); + + } + + @Override + public void incrementProgress() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + progressBar.setValue(progressBar.getValue() + 1); + } + }); + + } + + @Override + public void showIdleDialog(final ActionListener cancelListener, final String cancelCommand) { + log.debug("scheduling idle dialog"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("show idle dialog"); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + mainPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + + JLabel infoLabel = new JLabel(); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + + if (renderHeaderPanel) { + titleLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); + infoLabel.setText(cardmgmtMessages.getString(LABEL_ACTIVATION)); + } else { + infoLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); + } + + helpListener.setHelpTopic(HELP_ACTIVATION); + + progressBar.setIndeterminate(true); + progressBar.setStringPainted(true); + progressBar.setString(""); //not string painted progressbar is smaller + + JLabel stepLabel = new JLabel(); + stepLabel.setFont(stepLabel.getFont().deriveFont(stepLabel.getFont().getStyle() & ~java.awt.Font.BOLD, stepLabel.getFont().getSize()-2)); + stepLabel.setText(cardmgmtMessages.getString(LABEL_ACTIVATION_IDLE)); + + 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) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(stepLabel) + .addComponent(progressBar))); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(infoVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(stepLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(progressBar))); + + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + 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(); + + } + }); + + } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java new file mode 100644 index 00000000..860a1097 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java @@ -0,0 +1,33 @@ +/* + * 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.awt.event.ActionListener; + +/** + * + * @author Clemens Orthacker + */ +public interface ActivationGUIFacade extends BKUGUIFacade { + + public void showActivationProgressDialog(int currentStep, int maxProgress, ActionListener cancelListener, String cancelCommand); + + public void incrementProgress(); + + public void showIdleDialog(ActionListener cancelListener, String cancelCommand); + +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java new file mode 100644 index 00000000..4059f0e2 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java @@ -0,0 +1,52 @@ +/* + * 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.awt.Container; +import java.net.URL; +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * Common superclass for Activation and PinManagement GUIs + * + * @author Clemens Orthacker + */ +public class CardMgmtGUI extends BKUGUIImpl { + + public static final String CARDMGMT_MESSAGES_BUNDLE = "at/gv/egiz/bku/gui/ActivationMessages"; + + protected ResourceBundle cardmgmtMessages; + + public CardMgmtGUI(Container contentPane, + Locale locale, + Style guiStyle, + URL backgroundImgURL, + AbstractHelpListener helpListener) { + super(contentPane, locale, guiStyle, backgroundImgURL, helpListener); + + if (locale != null) { + Locale lang = new Locale(locale.getLanguage().substring(0,2)); + log.debug("loading applet resources for language: " + lang.toString()); + cardmgmtMessages = ResourceBundle.getBundle(CARDMGMT_MESSAGES_BUNDLE, lang); + } else { + cardmgmtMessages = ResourceBundle.getBundle(CARDMGMT_MESSAGES_BUNDLE); + } + + } +} 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 new file mode 100644 index 00000000..8acf051e --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -0,0 +1,159 @@ +/* + * 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.awt.Container; +import java.awt.event.ActionListener; +import java.net.URL; +import java.util.Locale; +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.LayoutStyle; +import javax.swing.SwingUtilities; + +/** + * TODO pull out ResourceBundle to common superclass for activationGUI and pinMgmtGUI + * @author Clemens Orthacker + */ +public class PINManagementGUI extends ActivationGUI implements PINManagementGUIFacade { + + 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 PINManagementGUI(Container contentPane, + Locale locale, + Style guiStyle, + URL backgroundImgURL, + AbstractHelpListener helpListener) { + super(contentPane, locale, guiStyle, backgroundImgURL, helpListener); + } + + @Override + public void showPINManagementDialog(final PINStatusProvider pinStatusProvider, + final ActionListener activateListener, final String activateCmd, + final ActionListener changeListener, final String changeCmd, + final ActionListener unblockListener, final String unblockCmd, + final ActionListener cancelListener, final String cancelCmd) { +// try { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + log.debug("show PIN management dialog"); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + helpListener.setHelpTopic(HELP_PINMGMT); + + JLabel mgmtLabel = new JLabel(); + mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + + if (renderHeaderPanel) { + titleLabel.setText(cardmgmtMessages.getString(TITLE_PINMGMT)); + mgmtLabel.setText(cardmgmtMessages.getString(MESSAGE_PINMGMT)); + } else { + mgmtLabel.setText(cardmgmtMessages.getString(TITLE_PINMGMT)); + } + + + + + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(mgmtLabel); + GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(mgmtLabel); + if (!renderHeaderPanel) { + messageHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + messageVertical + .addComponent(helpLabel); + } + + mainPanelLayout.setHorizontalGroup(messageHorizontal); + mainPanelLayout.setVerticalGroup(messageVertical); + + + JButton activateButton = new JButton(); + activateButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + activateButton.setText(cardmgmtMessages.getString(BUTTON_ACTIVATE)); + activateButton.setEnabled(true);//false); + activateButton.setActionCommand(activateCmd); + activateButton.addActionListener(activateListener); + + JButton changeButton = new JButton(); + changeButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + changeButton.setText(cardmgmtMessages.getString(BUTTON_CHANGE)); + changeButton.setEnabled(false); + changeButton.setActionCommand(changeCmd); + changeButton.addActionListener(changeListener); + + JButton unblockButton = new JButton(); + unblockButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + unblockButton.setText(cardmgmtMessages.getString(BUTTON_UNBLOCK)); + unblockButton.setEnabled(false); + unblockButton.setActionCommand(unblockCmd); + unblockButton.addActionListener(unblockListener); + + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + cancelButton.setText(messages.getString(BUTTON_CANCEL)); + cancelButton.setActionCommand(cancelCmd); + cancelButton.addActionListener(cancelListener); + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(activateButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(changeButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(unblockButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + + GroupLayout.Group buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(activateButton) + .addComponent(changeButton) + .addComponent(unblockButton) + .addComponent(cancelButton); + + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); + buttonPanelLayout.setVerticalGroup(buttonVertical); + + contentPanel.validate(); + + } + }); + +// } catch (Exception ex) { +// log.error(ex.getMessage(), ex); +// showErrorDialog(ERR_UNKNOWN_WITH_PARAM, new Object[] {ex.getMessage()}); +// } + } + + +} 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 new file mode 100644 index 00000000..3d653fab --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.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.bku.gui; + +import java.awt.event.ActionListener; + +/** + * + * @author Clemens Orthacker + */ +public interface PINManagementGUIFacade extends BKUGUIFacade { + + public static final String HELP_PINMGMT = "help.pin.mgmt"; + public static final String TITLE_PINMGMT = "title.pin.mgmt"; + public static final String MESSAGE_PINMGMT = "message.pin.mgmt"; + + public void showPINManagementDialog(PINStatusProvider pinStatusProvider, ActionListener activateListener, String activateCmd, ActionListener changeListener, String changeCmd, ActionListener unblockListener, String unblockCmd, ActionListener cancelListener, String cancelCmd); + +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java new file mode 100644 index 00000000..73fa0920 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java @@ -0,0 +1,32 @@ +/* + * 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.smcc.SignatureCardException; + +/** + * + * @author Clemens Orthacker + */ +public interface PINStatusProvider { + + public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED }; + + public STATUS getPINStatus(int pin) throws SignatureCardException; + +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ActivationApplet.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ActivationApplet.java new file mode 100644 index 00000000..68f0cb72 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ActivationApplet.java @@ -0,0 +1,90 @@ +/* + * 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.gui.AbstractHelpListener; +import at.gv.egiz.bku.gui.ActivationGUI; +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.BKUGUIFacade.Style; +import at.gv.egiz.bku.online.applet.BKUApplet; +import at.gv.egiz.bku.smccstal.AbstractSMCCSTAL; +import at.gv.egiz.bku.smccstal.ext.CardMgmtRequestHandler; +import at.gv.egiz.stal.ext.APDUScriptRequest; +import at.gv.egiz.stal.service.STALPortType; +import at.gv.egiz.stal.service.translator.STALTranslator; +import at.gv.egiz.stalx.service.STALService; +import at.gv.egiz.stalx.service.translator.STALXTranslationHandler; +import java.awt.Container; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Locale; +import javax.xml.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public class ActivationApplet extends BKUApplet { + + private static final long serialVersionUID = 1L; + private static Log log = LogFactory.getLog(ActivationApplet.class); + + @Override + public void init() { + super.init(); + if (worker instanceof AbstractSMCCSTAL) { + CardMgmtRequestHandler handler = new CardMgmtRequestHandler(); + ((AbstractSMCCSTAL) worker).addRequestHandler(APDUScriptRequest.class, handler); + log.debug("Registered CardMgmtRequestHandler"); + } else { + log.warn("Cannot register CardMgmtRequestHandler."); + } + } + + /** + * creates a STAL-X enabled webservice port + * @return + * @throws java.net.MalformedURLException + */ + @Override + public 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); + log.info("creating STAL-X enabled webservice port"); + STALService stal = new STALService(wsdlURL, endpointName); + return stal.getSTALPort(); + } + + @Override + public STALTranslator getSTALTranslator() { + STALTranslator translator = super.getSTALTranslator(); + translator.registerTranslationHandler(new STALXTranslationHandler()); + return translator; + } + + @Override + protected BKUGUIFacade createGUI(Container contentPane, + Locale locale, + Style guiStyle, + URL backgroundImgURL, + AbstractHelpListener helpListener) { + return new ActivationGUI(contentPane, locale, guiStyle, backgroundImgURL, helpListener); + } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java new file mode 100644 index 00000000..72d06618 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java @@ -0,0 +1,50 @@ +/* + * 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.gui.AbstractHelpListener; +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUI; +import java.awt.Container; +import java.net.URL; +import java.util.Locale; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public class PINManagementApplet extends BKUApplet { + + private static final long serialVersionUID = 1L; + private static Log log = LogFactory.getLog(PINManagementApplet.class); + + @Override + protected BKUGUIFacade createGUI(Container contentPane, + Locale locale, + BKUGUIFacade.Style guiStyle, + URL backgroundImgURL, + AbstractHelpListener helpListener) { + return new PINManagementGUI(contentPane, locale, guiStyle, backgroundImgURL, helpListener); + } + + @Override + protected AppletBKUWorker createBKUWorker(BKUApplet applet, BKUGUIFacade gui) { + return new PINManagementBKUWorker(applet, gui); + } +} 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 new file mode 100644 index 00000000..e65d98ca --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java @@ -0,0 +1,112 @@ +/* + * 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.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.smccstal.ext.PINMgmtRequestHandler; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.ext.ActivatePINRequest; +import at.gv.egiz.stal.ext.ChangePINRequest; +import at.gv.egiz.stal.ext.UnblockPINRequest; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Clemens Orthacker + */ +public class PINManagementBKUWorker extends AppletBKUWorker { + + protected PINMgmtRequestHandler handler = new PINMgmtRequestHandler(); + protected PINManagementActionListener listener = new PINManagementActionListener(); + + public PINManagementBKUWorker(BKUApplet applet, BKUGUIFacade gui) { + super(applet, gui); + handlerMap.clear(); +// PINMgmtRequestHandler handler = new PINMgmtRequestHandler(); +// addRequestHandler(ActivatePINRequest.class, handler); +// addRequestHandler(ChangePINRequest.class, handler); +// addRequestHandler(UnblockPINRequest.class, handler); + } + + @Override + public void run() { + gui.showWelcomeDialog(); + + try { + + if (waitForCard()) { + gui.showErrorDialog("no card, canceled PIN mgmt dialog", null); + } + + actionCommandList.clear(); + actionCommandList.add("cancel"); + + ((PINManagementGUIFacade) gui).showPINManagementDialog(handler, + listener, "activate", + listener, "change", + listener, "unblock", + this, "cancel"); + + waitForAction(); + + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + showErrorDialog(BKUGUIFacade.ERR_UNKNOWN_WITH_PARAM, ex); + } finally { + if (signatureCard != null) { + signatureCard.disconnect(false); + } + } + + applet.sendRedirect(sessionId); + } + + protected class PINManagementActionListener implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + try { + String cmd = e.getActionCommand(); + if ("activate".equals(cmd)) { + //create STAL request, call handle(req) + ActivatePINRequest stalReq = new ActivatePINRequest(); + STALResponse stalResp = handler.handleRequest(stalReq); + gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN_WITH_PARAM, new Object[]{"debug"}, this, "back"); + } else if ("change".equals(cmd)) { + } else if ("unblock".equals(cmd)) { + } else if ("back".equals(cmd)) { + + ((PINManagementGUIFacade) gui).showPINManagementDialog(handler, + this, "activate", + this, "change", + this, "unblock", + PINManagementBKUWorker.this, "cancel"); + + } + } catch (InterruptedException ex) { + log.fatal(ex); + } + } + } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ext/BKUAppletExt.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ext/BKUAppletExt.java deleted file mode 100644 index d9df5536..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ext/BKUAppletExt.java +++ /dev/null @@ -1,80 +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.ext; - -import at.gv.egiz.stal.service.translator.STALTranslator; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.online.applet.BKUApplet; -import at.gv.egiz.bku.smccstal.AbstractBKUWorker; -import at.gv.egiz.bku.smccstal.ext.CardMgmtRequestHandler; -import at.gv.egiz.stal.ext.APDUScriptRequest; -import at.gv.egiz.stal.service.STALPortType; -import at.gv.egiz.stalx.service.STALService; -import at.gv.egiz.stalx.service.translator.STALXTranslationHandler; -import java.net.MalformedURLException; -import java.net.URL; -import javax.xml.namespace.QName; - -/** - * @author mcentner - */ -public class BKUAppletExt extends BKUApplet { - - private static final long serialVersionUID = 1L; - private static Log log = LogFactory.getLog(BKUAppletExt.class); - - @Override - public void init() { - super.init(); - if (worker instanceof AbstractBKUWorker) { - CardMgmtRequestHandler handler = new CardMgmtRequestHandler(); - ((AbstractBKUWorker) worker).addRequestHandler(APDUScriptRequest.class, handler); - log.debug("Registered CardMgmtRequestHandler"); - } else { - log.warn("Cannot register CardMgmtRequestHandler."); - } - } - - /** - * creates a STAL-X enabled webservice port - * @return - * @throws java.net.MalformedURLException - */ - @Override - 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); - log.info("creating STAL-X enabled webservice port"); - STALService stal = new STALService(wsdlURL, endpointName); - return stal.getSTALPort(); - } - - @Override - protected STALTranslator getSTALTranslator() { - STALTranslator translator = super.getSTALTranslator(); - translator.registerTranslationHandler(new STALXTranslationHandler()); - return translator; - } - - -} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/CardMgmtRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/CardMgmtRequestHandler.java index f499de7e..769342e7 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/CardMgmtRequestHandler.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/CardMgmtRequestHandler.java @@ -19,6 +19,7 @@ */ package at.gv.egiz.bku.smccstal.ext; +import at.gv.egiz.bku.gui.ActivationGUIFacade; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -45,12 +46,13 @@ 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 { +public class CardMgmtRequestHandler extends AbstractRequestHandler implements ActionListener { /** * Logging facility. @@ -61,7 +63,12 @@ public class CardMgmtRequestHandler extends AbstractRequestHandler { * The sequence counter. */ private int sequenceNum = 0; - + + /** + * display script num + */ + private int currentActivationScript = 0; + @Override public STALResponse handleRequest(STALRequest request) throws InterruptedException { @@ -69,7 +76,8 @@ public class CardMgmtRequestHandler extends AbstractRequestHandler { // APDU Script Request if (request instanceof APDUScriptRequest) { - gui.showWaitDialog("CardChannel"); + currentActivationScript++; + log.debug("handling APDU script " + currentActivationScript); Card icc = card.getCard(); @@ -81,20 +89,28 @@ public class CardMgmtRequestHandler extends AbstractRequestHandler { 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 " + sequenceNum + " " + commandAPDU.toString()); + log.debug("Transmit APDU (sequence=" + sequenceNum + ")"); + log.trace(commandAPDU.toString()); ResponseAPDU responseAPDU = channel.transmit(commandAPDU); - log.debug("" + responseAPDU); + log.trace(responseAPDU.toString()); byte[] sw = new byte[] { (byte) (0xFF & responseAPDU.getSW1()), @@ -105,16 +121,22 @@ public class CardMgmtRequestHandler extends AbstractRequestHandler { if (command.getExpectedSW() != null && !Arrays.equals(sw, command.getExpectedSW())) { // unexpected SW - log.info("Got unexpected SW. APDU-script execution stopped."); + 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(); - responses.add(new ATR(icc.getATR().getBytes())); - + 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(); } } @@ -125,6 +147,9 @@ public class CardMgmtRequestHandler extends AbstractRequestHandler { } 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(); @@ -133,7 +158,8 @@ public class CardMgmtRequestHandler extends AbstractRequestHandler { } } - gui.showWaitDialog("wait for server..."); + log.trace("done handling APDU script " + currentActivationScript + ", return response containing " + responses.size() + " elements"); + ((ActivationGUIFacade) gui).showIdleDialog(this, "cancel"); return new APDUScriptResponse(responses); } else { diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java new file mode 100644 index 00000000..b2d34ff2 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java @@ -0,0 +1,93 @@ +/* + * 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.PINStatusProvider; +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.ActivatePINRequest; +import at.gv.egiz.stal.ext.ChangePINRequest; +import at.gv.egiz.stal.ext.UnblockPINRequest; +import java.util.logging.Level; +import java.util.logging.Logger; +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; + +/** + * + * @author Clemens Orthacker + */ +public class PINMgmtRequestHandler extends AbstractRequestHandler implements PINStatusProvider { + + protected static final Log log = LogFactory.getLog(PINMgmtRequestHandler.class); + + @Override + public STALResponse handleRequest(STALRequest request) throws InterruptedException { + if (request instanceof ActivatePINRequest) { + log.error("not implemented yet"); + return new ErrorResponse(1000); + + } else if (request instanceof ChangePINRequest) { + log.error("not implemented yet"); + return new ErrorResponse(1000); + + } else if (request instanceof UnblockPINRequest) { + log.error("not implemented yet"); + return new ErrorResponse(1000); + + } else { + log.error("Got unexpected STAL request: " + request); + return new ErrorResponse(1000); + } + } + + @Override + public boolean requireCard() { + return true; + } + + @Override + public STATUS getPINStatus(int pin) throws SignatureCardException { + try { + Card icc = card.getCard(); + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + CommandAPDU verifyAPDU = new CommandAPDU(new byte[] {(byte) 0x00} ); + ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); + byte sw1 = (byte) responseAPDU.getSW1(); + byte[] sw = new byte[] { + (byte) (0xFF & responseAPDU.getSW1()), + (byte) (0xFF & responseAPDU.getSW2()) }; + + icc.endExclusive(); + return STATUS.ACTIV; + } catch (CardException ex) { + log.error("Failed to get PIN status: " + ex.getMessage()); + throw new SignatureCardException("Failed to get PIN status", ex); + } + } + +} 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 new file mode 100644 index 00000000..469af15f --- /dev/null +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -0,0 +1,24 @@ +# 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. + +title.activation=Aktivierung +title.pin.mgmt=PIN Verwaltung +message.pin.mgmt=under construction +label.activation=e-card Aktivierungsprozess +label.activation.step=Schritt {0} +label.activation.idle=Warte auf Server... +button.activate=Aktivieren +button.change=\u00C4ndern +button.unblock=Entsperren \ No newline at end of file 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 new file mode 100644 index 00000000..16ac7d0b --- /dev/null +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -0,0 +1,24 @@ +# 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. + +title.activation=Aktivation +title.pin.mgmt=PIN Management +message.pin.mgmt=under construction +label.activation=e-card activation process +label.activation.step=Step {0} +label.activation.idle=Wait for server... +button.activate=Activate +button.change=Change +button.unblock=Unblock \ No newline at end of file diff --git a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java new file mode 100644 index 00000000..95c5c678 --- /dev/null +++ b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java @@ -0,0 +1,62 @@ +/* +* 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. + */ + +package at.gv.egiz.bku.gui; + +import java.awt.Container; +import java.awt.Dimension; +import javax.swing.JFrame; +import org.junit.Ignore; +import org.junit.Test; + + +/** + * + * @author clemens + */ +@Ignore +public class ActivationGuiTest { + + @Test + public void testBKUGUI() { + JFrame testFrame = new JFrame("BKUGUITest"); + Container contentPane = testFrame.getContentPane(); + contentPane.setPreferredSize(new Dimension(152, 145)); +// contentPane.setPreferredSize(new Dimension(300, 190)); + ActivationGUIFacade gui = new ActivationGUI(contentPane, null, BKUGUIFacade.Style.tiny, null, null); + BKUGUIWorker worker = new BKUGUIWorker(); + worker.init(gui); + testFrame.pack(); + testFrame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + testFrame.setVisible(true); + new Thread(worker).start(); + + while(true) ; + } + + @Test + public void dummyTest() { + } + +// public static void main(String[] args) { +// new BKUGUITest().testBKUGUI(); +// } +} 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 new file mode 100644 index 00000000..669a63fc --- /dev/null +++ b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -0,0 +1,204 @@ +/* + * 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. + */ +package at.gv.egiz.bku.gui; + +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author clemens + */ +public class BKUGUIWorker implements Runnable { + + ActivationGUIFacade gui; + + public void init(ActivationGUIFacade gui) { + this.gui = gui; + } + + @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 ByteArrayHashDataInput( + "Ich bin ein einfacher Text mit Umlauten: öäüßéç@€\n123\n456\n\tHello, world!\n\nlkjsd\nnksdjf".getBytes(), + "ref-id-0000000000000000000000001", + "text/plain", + "UTF-8"); + + HashDataInput signedRef2 = new ByteArrayHashDataInput( + "HashDataInput_002".getBytes(), + "ref-id-000000002", + "application/xhtml+xml", + "UTF-8"); + + HashDataInput signedRef3 = new ByteArrayHashDataInput( + "HashDataInput_003".getBytes(), + "ref-id-000000003", + "application/xhtml+xml", + "UTF-8"); + + HashDataInput signedRef4 = new ByteArrayHashDataInput( + "HashDataInput_004".getBytes(), + "ref-id-000000004", + "text/xml", + "UTF-8"); + + // + List signedRefs = new ArrayList(); + signedRefs.add(signedRef1); + signedRefs.add(signedRef2); + signedRefs.add(signedRef3); + signedRefs.add(signedRef4); +// signedRefs.add(signedRef4); +// signedRefs.add(signedRef4); +// signedRefs.add(signedRef4); +// signedRefs.add(signedRef4); +// signedRefs = Collections.singletonList(signedRef1); + gui.showHashDataInputDialog(signedRefs, returnListener, "return"); + } + }; + + + +// 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.showErrorDialog(BKUGUIFacade.ERR_NO_PCSC, null, null, null); + +// 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.showActivationProgressDialog(1, 3, null, null); + + gui.incrementProgress(); + + Thread.sleep(1000); + + gui.incrementProgress(); + + Thread.sleep(1000); + + gui.incrementProgress(); + + + Thread.sleep(1000); + + gui.showIdleDialog(null, 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(); + } + } +} 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 new file mode 100644 index 00000000..8d8b0385 --- /dev/null +++ b/BKUAppletExt/src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java @@ -0,0 +1,434 @@ +/* + * 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 + */ +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/BKUAppletExt/src/test/resources/appletTest.html b/BKUAppletExt/src/test/resources/appletTest.html index f7a47d0a..9add4309 100644 --- a/BKUAppletExt/src/test/resources/appletTest.html +++ b/BKUAppletExt/src/test/resources/appletTest.html @@ -17,10 +17,10 @@
- - + -- cgit v1.2.3 From bd18d9084fd139aaae40ad8d525c1d0e626f2e5e Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 12 Feb 2009 09:31:43 +0000 Subject: ignore test (assumes e-card) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@308 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/test/java/at/gv/egiz/bku/smccstal/ext/FileSystemTest.java | 1 + 1 file changed, 1 insertion(+) (limited to 'BKUAppletExt/src/test') 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 index 8d8b0385..5fa3cbd7 100644 --- 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 @@ -44,6 +44,7 @@ import static org.junit.Assert.*; * * @author Clemens Orthacker */ +@Ignore public class FileSystemTest { /** asign premium */ -- cgit v1.2.3 From 6576428966f1e3d688269a407b072fb01f9f7647 Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 26 Feb 2009 19:39:00 +0000 Subject: 1.1 candidate (activation) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@309 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/online/applet/AppletBKUWorker.java | 9 +- .../java/at/gv/egiz/bku/gui/PINManagementGUI.java | 519 ++++- .../at/gv/egiz/bku/gui/PINManagementGUIFacade.java | 47 +- .../java/at/gv/egiz/bku/gui/PINSpecRenderer.java | 39 + .../java/at/gv/egiz/bku/gui/PINStatusProvider.java | 32 - .../java/at/gv/egiz/bku/gui/PINStatusRenderer.java | 63 + .../at/gv/egiz/bku/gui/PINStatusTableModel.java | 60 + .../bku/online/applet/PINManagementApplet.java | 3 +- .../bku/online/applet/PINManagementBKUWorker.java | 82 +- .../smccstal/ext/PINManagementRequestHandler.java | 331 ++++ .../bku/smccstal/ext/PINMgmtRequestHandler.java | 93 - .../gv/egiz/bku/gui/ActivationMessages.properties | 28 +- .../egiz/bku/gui/ActivationMessages_en.properties | 30 +- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 4 +- BKUAppletExt/src/test/resources/appletTest.html | 2 +- .../main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java | 8 +- .../main/java/at/gv/egiz/bku/gui/PinDocument.java | 28 +- .../at/gv/egiz/bku/gui/Messages.properties | 4 +- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 2 +- .../at/gv/egiz/stal/ext/ActivatePINRequest.java | 28 - .../java/at/gv/egiz/stal/ext/ChangePINRequest.java | 28 - .../at/gv/egiz/stal/ext/PINManagementRequest.java | 31 + .../at/gv/egiz/stal/ext/PINManagementResponse.java | 28 + .../at/gv/egiz/stal/ext/UnblockPINRequest.java | 28 - .../egiz/bku/slcommands/impl/xsect/DataObject.java | 2078 ++++++++++---------- .../egiz/bku/slcommands/impl/xsect/Signature.java | 5 +- .../bku/slcommands/impl/xsect/SignatureTest.java | 1505 +++++++------- .../egiz/bku/slcommands/impl/TransformsInfo_2.xml | 397 ++++ smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 25 +- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 10 + smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java | 30 +- .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 25 +- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 14 +- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 5 +- .../at/gv/egiz/bku/smccstal/AbstractBKUWorker.java | 3 + .../java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java | 9 +- .../java/at/gv/egiz/marshal/NamespacePrefix.java | 34 + .../gv/egiz/marshal/NamespacePrefixMapperImpl.java | 16 +- .../at/gv/egiz/slbinding/RedirectEventFilter.java | 389 ++-- .../gv/egiz/slbinding/impl/TransformsInfoType.java | 1 + .../at/gv/egiz/slbinding/impl/XMLContentType.java | 2 +- .../org/w3/_2000/_09/xmldsig_/ObjectFactory.java | 1 + .../org/w3/_2000/_09/xmldsig_/TransformsType.java | 2 +- .../java/at/gv/egiz/slbinding/RedirectTest.java | 29 +- .../CreateXMLSignatureRequest02.xml_redirect.txt | 5 +- 45 files changed, 3813 insertions(+), 2299 deletions(-) create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java create mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java delete mode 100644 STALExt/src/main/java/at/gv/egiz/stal/ext/ActivatePINRequest.java delete mode 100644 STALExt/src/main/java/at/gv/egiz/stal/ext/ChangePINRequest.java create mode 100644 STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementRequest.java create mode 100644 STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementResponse.java delete mode 100644 STALExt/src/main/java/at/gv/egiz/stal/ext/UnblockPINRequest.java create mode 100644 bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/impl/TransformsInfo_2.xml create mode 100644 utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java (limited to 'BKUAppletExt/src/test') 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 5a57ef18..8c1bd2bd 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 @@ -195,11 +195,16 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { } } + /** + * + * @param err_code + * @param ex if not null, the message will be appended as parameter to the error message + */ protected void showErrorDialog(String err_code, Exception ex) { actionCommandList.clear(); actionCommandList.add("ok"); - gui.showErrorDialog(err_code, - new Object[]{ex.getMessage()}, this, "ok"); + Object[] params = (ex != null) ? new Object[] { ex.getMessage() } : null; + gui.showErrorDialog(err_code, params, this, "ok"); try { waitForAction(); } catch (InterruptedException e) { 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 8acf051e..8eef8aea 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 @@ -17,15 +17,28 @@ package at.gv.egiz.bku.gui; +import at.gv.egiz.smcc.PINSpec; import java.awt.Container; +import java.awt.Cursor; +import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; import java.net.URL; +import java.text.MessageFormat; import java.util.Locale; +import java.util.Map; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JLabel; +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; /** * TODO pull out ResourceBundle to common superclass for activationGUI and pinMgmtGUI @@ -33,9 +46,10 @@ import javax.swing.SwingUtilities; */ public class PINManagementGUI extends ActivationGUI implements PINManagementGUIFacade { - public static final String BUTTON_ACTIVATE = "button.activate"; - public static final String BUTTON_UNBLOCK = "button.unblock"; - public static final String BUTTON_CHANGE = "button.change"; + /** remember the pinfield to return to worker */ + protected JPasswordField oldPinField; + /** remember the pinSpec to return to worker */ + protected PINSpec pinSpec; public PINManagementGUI(Container contentPane, Locale locale, @@ -46,12 +60,31 @@ public class PINManagementGUI extends ActivationGUI implements PINManagementGUIF } @Override - public void showPINManagementDialog(final PINStatusProvider pinStatusProvider, - final ActionListener activateListener, final String activateCmd, - final ActionListener changeListener, final String changeCmd, - final ActionListener unblockListener, final String unblockCmd, - final ActionListener cancelListener, final String cancelCmd) { -// try { + public char[] getOldPin() { + if (oldPinField != null) { + char[] pin = oldPinField.getPassword(); + oldPinField = null; + return pin; + } + return null; + } + + @Override + public PINSpec getSelectedPIN() { + return pinSpec; + } + + @Override + public void showPINManagementDialog(final Map pins, + final ActionListener activateListener, + final String activateCmd, + final String changeCmd, + final String unblockCmd, + final ActionListener cancelListener, + final String cancelCmd) { + + log.debug("scheduling PIN managment dialog"); + SwingUtilities.invokeLater(new Runnable() { @Override @@ -68,13 +101,76 @@ public class PINManagementGUI extends ActivationGUI implements PINManagementGUIF if (renderHeaderPanel) { titleLabel.setText(cardmgmtMessages.getString(TITLE_PINMGMT)); - mgmtLabel.setText(cardmgmtMessages.getString(MESSAGE_PINMGMT)); + String infoPattern = cardmgmtMessages.getString(MESSAGE_PINMGMT); + mgmtLabel.setText(MessageFormat.format(infoPattern, pins.size())); } else { mgmtLabel.setText(cardmgmtMessages.getString(TITLE_PINMGMT)); } + final PINStatusTableModel tableModel = new PINStatusTableModel(pins); + final JTable pinStatusTable = new JTable(tableModel); + 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()); + } + } + }); + + final JButton activateButton = new JButton(); + activateButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + activateButton.addActionListener(activateListener); + + pinStatusTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + pinStatusTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(final ListSelectionEvent e) { + //invoke later to allow thread to paint selection background + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + ListSelectionModel lsm = (ListSelectionModel) e.getSource(); + int selectionIdx = lsm.getMinSelectionIndex(); + if (selectionIdx >= 0) { + pinSpec = (PINSpec) tableModel.getValueAt(selectionIdx, 0); + STATUS status = (STATUS) tableModel.getValueAt(selectionIdx, 1); + + if (status == STATUS.NOT_ACTIV) { + activateButton.setText(cardmgmtMessages.getString(BUTTON_ACTIVATE)); + activateButton.setEnabled(true); + activateButton.setActionCommand(activateCmd); + } else if (status == STATUS.BLOCKED) { + activateButton.setText(cardmgmtMessages.getString(BUTTON_UNBLOCK)); + activateButton.setEnabled(true); + activateButton.setActionCommand(unblockCmd); + } else if (status == STATUS.ACTIV) { + activateButton.setText(cardmgmtMessages.getString(BUTTON_CHANGE)); + activateButton.setEnabled(true); + activateButton.setActionCommand(changeCmd); + } else { + activateButton.setText(cardmgmtMessages.getString(BUTTON_ACTIVATE)); + activateButton.setEnabled(false); + } + } + } + }); + } + }); + + //select first entry + pinStatusTable.getSelectionModel().setSelectionInterval(0, 0); + + JScrollPane pinStatusScrollPane = new JScrollPane(pinStatusTable); GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); @@ -91,30 +187,16 @@ public class PINManagementGUI extends ActivationGUI implements PINManagementGUIF .addComponent(helpLabel); } - mainPanelLayout.setHorizontalGroup(messageHorizontal); - mainPanelLayout.setVerticalGroup(messageVertical); + mainPanelLayout.setHorizontalGroup( + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(messageHorizontal) + .addComponent(pinStatusScrollPane, 0, 0, Short.MAX_VALUE)); - - JButton activateButton = new JButton(); - activateButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - activateButton.setText(cardmgmtMessages.getString(BUTTON_ACTIVATE)); - activateButton.setEnabled(true);//false); - activateButton.setActionCommand(activateCmd); - activateButton.addActionListener(activateListener); - - JButton changeButton = new JButton(); - changeButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - changeButton.setText(cardmgmtMessages.getString(BUTTON_CHANGE)); - changeButton.setEnabled(false); - changeButton.setActionCommand(changeCmd); - changeButton.addActionListener(changeListener); - - JButton unblockButton = new JButton(); - unblockButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - unblockButton.setText(cardmgmtMessages.getString(BUTTON_UNBLOCK)); - unblockButton.setEnabled(false); - unblockButton.setActionCommand(unblockCmd); - unblockButton.addActionListener(unblockListener); + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(messageVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinStatusScrollPane, 0, 0, pinStatusTable.getPreferredSize().height+3)); JButton cancelButton = new JButton(); cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -129,30 +211,377 @@ public class PINManagementGUI extends ActivationGUI implements PINManagementGUIF .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(activateButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(changeButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(unblockButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); GroupLayout.Group buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(activateButton) - .addComponent(changeButton) - .addComponent(unblockButton) .addComponent(cancelButton); buttonPanelLayout.setHorizontalGroup(buttonHorizontal); buttonPanelLayout.setVerticalGroup(buttonVertical); contentPanel.validate(); - } }); + } + + @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(false, pin, okListener, okCommand, cancelListener, cancelCommand); + } + + + private void showPINDialog(final boolean changePin, final PINSpec pinSpec, + final ActionListener okListener, final String okCommand, + final ActionListener cancelListener, final String cancelCommand) { + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + String HELP_TOPIC, TITLE, MESSAGE_MGMT; + if (changePin) { + log.debug("show change pin dialog"); + HELP_TOPIC = HELP_PINMGMT; + TITLE = TITLE_CHANGE_PIN; + MESSAGE_MGMT = MESSAGE_CHANGE_PIN; + } else { + log.debug("show activate pin dialog"); + HELP_TOPIC = HELP_PINMGMT; + TITLE = TITLE_ACTIVATE_PIN; + MESSAGE_MGMT = MESSAGE_ACTIVATE_PIN; + oldPinField = null; + } + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + helpListener.setHelpTopic(HELP_TOPIC); + + JLabel mgmtLabel = new JLabel(); + mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + + if (renderHeaderPanel) { + titleLabel.setText(cardmgmtMessages.getString(TITLE)); + String mgmtPattern = cardmgmtMessages.getString(MESSAGE_MGMT); + if (shortText) { + mgmtLabel.setText(MessageFormat.format(mgmtPattern, "PIN")); + } else { + mgmtLabel.setText(MessageFormat.format(mgmtPattern, pinSpec.getLocalizedName())); + } + } else { + mgmtLabel.setText(cardmgmtMessages.getString(TITLE)); + } + + JButton okButton = new JButton(); + okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + okButton.setText(messages.getString(BUTTON_OK)); + okButton.setEnabled(false); + okButton.setActionCommand(okCommand); + okButton.addActionListener(okListener); + + JLabel pinLabel = new JLabel(); + pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + String pinLabelPattern = (changePin) ? cardmgmtMessages.getString(LABEL_NEW_PIN) : messages.getString(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 = cardmgmtMessages.getString(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()) { + okListener.actionPerformed(e); + } + } + }); + + JLabel oldPinLabel = null; + if (changePin) { + oldPinLabel = new JLabel(); + oldPinLabel.setFont(oldPinLabel.getFont().deriveFont(oldPinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + String oldPinLabelPattern = cardmgmtMessages.getString(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(); + } + } + }); + } + + JLabel pinsizeLabel = new JLabel(); + pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, pinsizeLabel.getFont().getSize()-2)); + String pinsizePattern = messages.getString(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); + } -// } catch (Exception ex) { -// log.error(ex.getMessage(), ex); -// showErrorDialog(ERR_UNKNOWN_WITH_PARAM, new Object[] {ex.getMessage()}); -// } + 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) { + pinHorizontal + .addGroup(mainPanelLayout.createSequentialGroup() + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(oldPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); + + pinVertical + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(oldPinLabel) + .addComponent(oldPinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); + } else { + pinHorizontal + .addGroup(mainPanelLayout.createSequentialGroup() + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .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 + .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) + .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)); + + 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(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); + + 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(true, 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(messages.getString(TITLE_ERROR)); + } + + helpListener.setHelpTopic(HELP_PINMGMT); + + String errorMsgPattern = cardmgmtMessages.getString(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(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)); + okButton.setText(messages.getString(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(); + } + }); } 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 3d653fab..2a8f28d2 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 @@ -17,7 +17,9 @@ package at.gv.egiz.bku.gui; +import at.gv.egiz.smcc.PINSpec; import java.awt.event.ActionListener; +import java.util.Map; /** * @@ -27,8 +29,49 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String HELP_PINMGMT = "help.pin.mgmt"; 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_UNBLOCK_PIN = "title.unblock.pin"; public static final String MESSAGE_PINMGMT = "message.pin.mgmt"; - - public void showPINManagementDialog(PINStatusProvider pinStatusProvider, ActionListener activateListener, String activateCmd, ActionListener changeListener, String changeCmd, ActionListener unblockListener, String unblockCmd, ActionListener cancelListener, String cancelCmd); + 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_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_ACTIVATE = "err.activate"; + public static final String ERR_CHANGE = "err.change"; + public static final String ERR_UNBLOCK = "err.unblock"; + + 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 STATUS_ACTIVE = "status.active"; + public static final String STATUS_BLOCKED = "status.blocked"; + public static final String STATUS_NOT_ACTIVE = "status.not.active"; + public static final String STATUS_UNKNOWN = "status.unknown"; + + public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED, UNKNOWN }; + + public void showPINManagementDialog(Map pins, + ActionListener activateListener, String activateCmd, String changeCmd, String unblockCmd, + 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 char[] getOldPin(); + + public PINSpec getSelectedPIN(); } diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java new file mode 100644 index 00000000..e3d73e1f --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.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.bku.gui; + +import at.gv.egiz.smcc.PINSpec; +import javax.swing.table.DefaultTableCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public class PINSpecRenderer extends DefaultTableCellRenderer { + + private static final Log log = LogFactory.getLog(PINSpecRenderer.class); + + @Override + protected void setValue(Object value) { + PINSpec pinSpec = (PINSpec) value; + super.setText(pinSpec.getLocalizedName()); + } + +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java deleted file mode 100644 index 73fa0920..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java +++ /dev/null @@ -1,32 +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.smcc.SignatureCardException; - -/** - * - * @author Clemens Orthacker - */ -public interface PINStatusProvider { - - public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED }; - - public STATUS getPINStatus(int pin) throws SignatureCardException; - -} 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 new file mode 100644 index 00000000..2f8852ff --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java @@ -0,0 +1,63 @@ +/* + * 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.PINManagementGUIFacade.STATUS; +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; + +/** + * + * @author Clemens Orthacker + */ +public class PINStatusRenderer extends DefaultTableCellRenderer { + + private static final Log log = LogFactory.getLog(PINStatusRenderer.class); + + public static final Color RED = new Color(0.9f, 0.0f, 0.0f); + public static final Color GREEN = new Color(0.0f, 0.8f, 0.0f); + protected ResourceBundle messages; + + public PINStatusRenderer(ResourceBundle messages) { + this.messages = messages; + } + + @Override + protected void setValue(Object value) { + STATUS pinStatus = (STATUS) value; + super.setFont(super.getFont().deriveFont(super.getFont().getStyle() | Font.BOLD)); + + if (pinStatus == STATUS.NOT_ACTIV) { + super.setForeground(RED); + super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_NOT_ACTIVE) + ""); + } else if (pinStatus == STATUS.ACTIV) { + super.setForeground(GREEN); + super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_ACTIVE) + ""); + } else if (pinStatus == STATUS.BLOCKED) { + super.setForeground(RED); + super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_BLOCKED) + ""); + } else { + super.setForeground(Color.BLACK); + super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_UNKNOWN) + ""); + } + } +} 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 new file mode 100644 index 00000000..feaa5072 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.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.gui; + +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; + +/** + * + * @author Clemens Orthacker + */ +public class PINStatusTableModel extends DefaultTableModel { + + protected static final Log log = LogFactory.getLog(PINStatusTableModel.class); + protected Class[] types; + + public PINStatusTableModel(Map pinStatuses) { + super(0, 2); + if (pinStatuses == null) { + throw new RuntimeException("pinStatuses must not be null"); + } + log.trace(pinStatuses.size() + " PINs"); + types = new Class[] { PINSpec.class, STATUS.class }; + for (PINSpec pinSpec : pinStatuses.keySet()) { + addRow(new Object[] { pinSpec, pinStatuses.get(pinSpec) }); + } +// PINSpec activePIN = new PINSpec(0, 1, null, "active-PIN", (byte) 0x01); +// PINSpec blockedPIN = new PINSpec(0, 1, null, "blocked-PIN", (byte) 0x01); +// addRow(new Object[] { activePIN, PINStatusProvider.STATUS.ACTIV }); +// addRow(new Object[] { blockedPIN, PINStatusProvider.STATUS.BLOCKED }); + } + + @Override + public Class getColumnClass(int columnIndex) { + return types[columnIndex]; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java index 72d06618..d948ac03 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java @@ -19,6 +19,7 @@ package at.gv.egiz.bku.online.applet; import at.gv.egiz.bku.gui.AbstractHelpListener; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.PINManagementGUI; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; import java.awt.Container; import java.net.URL; import java.util.Locale; @@ -45,6 +46,6 @@ public class PINManagementApplet extends BKUApplet { @Override protected AppletBKUWorker createBKUWorker(BKUApplet applet, BKUGUIFacade gui) { - return new PINManagementBKUWorker(applet, gui); + return new PINManagementBKUWorker(applet, (PINManagementGUIFacade) gui); } } 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 e65d98ca..ffd83e42 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 @@ -18,35 +18,28 @@ package at.gv.egiz.bku.online.applet; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.PINManagementGUIFacade; -import at.gv.egiz.bku.smccstal.ext.PINMgmtRequestHandler; +import at.gv.egiz.bku.smccstal.ext.PINManagementRequestHandler; +import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.STALResponse; -import at.gv.egiz.stal.ext.ActivatePINRequest; -import at.gv.egiz.stal.ext.ChangePINRequest; -import at.gv.egiz.stal.ext.UnblockPINRequest; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Collection; +import at.gv.egiz.stal.ext.PINManagementRequest; +import at.gv.egiz.stal.ext.PINManagementResponse; import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** - * + * This BKU Worker does not connect to STAL webservice + * (no Internet connection permitted while activating PINs). + * * @author Clemens Orthacker */ public class PINManagementBKUWorker extends AppletBKUWorker { - protected PINMgmtRequestHandler handler = new PINMgmtRequestHandler(); - protected PINManagementActionListener listener = new PINManagementActionListener(); - - public PINManagementBKUWorker(BKUApplet applet, BKUGUIFacade gui) { + public PINManagementBKUWorker(BKUApplet applet, PINManagementGUIFacade gui) { super(applet, gui); handlerMap.clear(); -// PINMgmtRequestHandler handler = new PINMgmtRequestHandler(); -// addRequestHandler(ActivatePINRequest.class, handler); -// addRequestHandler(ChangePINRequest.class, handler); -// addRequestHandler(UnblockPINRequest.class, handler); + addRequestHandler(PINManagementRequest.class, new PINManagementRequestHandler()); } @Override @@ -54,22 +47,24 @@ public class PINManagementBKUWorker extends AppletBKUWorker { gui.showWelcomeDialog(); try { - - if (waitForCard()) { - gui.showErrorDialog("no card, canceled PIN mgmt dialog", null); + List responses = handleRequest(Collections.singletonList(new PINManagementRequest())); + + if (responses.size() == 1) { + STALResponse response = responses.get(0); + if (response instanceof PINManagementResponse) { + log.debug("PIN management dialog finished"); + } else if (response instanceof ErrorResponse) { + showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, null); + } else { + throw new RuntimeException("Invalid STAL response: " + response.getClass().getName()); + } + } else { + throw new RuntimeException("invalid number of STAL responses: " + responses.size()); } - actionCommandList.clear(); - actionCommandList.add("cancel"); - - ((PINManagementGUIFacade) gui).showPINManagementDialog(handler, - listener, "activate", - listener, "change", - listener, "unblock", - this, "cancel"); - - waitForAction(); - + } catch (RuntimeException ex) { + log.error("unexpected error: " + ex.getMessage(), ex); + showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, null); } catch (Exception ex) { log.error(ex.getMessage(), ex); showErrorDialog(BKUGUIFacade.ERR_UNKNOWN_WITH_PARAM, ex); @@ -82,31 +77,4 @@ public class PINManagementBKUWorker extends AppletBKUWorker { applet.sendRedirect(sessionId); } - protected class PINManagementActionListener implements ActionListener { - - @Override - public void actionPerformed(ActionEvent e) { - try { - String cmd = e.getActionCommand(); - if ("activate".equals(cmd)) { - //create STAL request, call handle(req) - ActivatePINRequest stalReq = new ActivatePINRequest(); - STALResponse stalResp = handler.handleRequest(stalReq); - gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN_WITH_PARAM, new Object[]{"debug"}, this, "back"); - } else if ("change".equals(cmd)) { - } else if ("unblock".equals(cmd)) { - } else if ("back".equals(cmd)) { - - ((PINManagementGUIFacade) gui).showPINManagementDialog(handler, - this, "activate", - this, "change", - this, "unblock", - PINManagementBKUWorker.this, "cancel"); - - } - } catch (InterruptedException ex) { - log.fatal(ex); - } - } } -} 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 new file mode 100644 index 00000000..fcef3191 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java @@ -0,0 +1,331 @@ +/* + * 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.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; +import at.gv.egiz.bku.smccstal.AbstractRequestHandler; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.util.SMCCHelper; +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; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +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; + +/** + * + * @author Clemens Orthacker + */ +public class PINManagementRequestHandler extends AbstractRequestHandler { + + public static final String ERR_NOPIN_SELECTED = "err.no.pin.selected"; + protected static final Log log = LogFactory.getLog(PINManagementRequestHandler.class); + +// protected ResourceBundle messages; + +// public PINManagementRequestHandler(ResourceBundle messages) { +// this.messages = messages; +// } + @Override + public STALResponse handleRequest(STALRequest request) throws InterruptedException { + if (request instanceof PINManagementRequest) { + + PINManagementGUIFacade gui = (PINManagementGUIFacade) this.gui; + + showPINManagementDialog(gui); + + while (true) { + + waitForAction(); + + if ("cancel".equals(actionCommand)) { + return new PINManagementResponse(); + } else if ("back".equals(actionCommand)) { + showPINManagementDialog(gui); + } else { + PINSpec selectedPIN = gui.getSelectedPIN(); + + if (selectedPIN == null) { + throw new RuntimeException("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 ("activate".equals(actionCommand)) { + try { + byte[] pin = encodePIN(gui.getPin()); + activatePIN(selectedPIN.getKID(), selectedPIN.getContextAID(), pin); + showPINManagementDialog(gui); + } 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)) { + try { + byte[] oldPin = encodePIN(gui.getOldPin()); //new byte[]{(byte) 0x25, (byte) 0x40, (byte) 0x01}; + byte[] pin = encodePIN(gui.getPin()); //new byte[]{(byte) 0x25, (byte) 0x40}; + changePIN(selectedPIN.getKID(), selectedPIN.getContextAID(), oldPin, pin); + showPINManagementDialog(gui); + } 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.error("unblock PIN not implemented"); + gui.showErrorDialog(PINManagementGUIFacade.ERR_UNBLOCK, null, this, "cancel"); + } else { + throw new RuntimeException("unsupported action " + actionCommand); + } + } + } + } else { + log.error("Got unexpected STAL request: " + request); + return new ErrorResponse(1000); + } + } + + @Override + public boolean requireCard() { + return true; + } + + /** + * pin.length < 4bit + * @param kid + * @param contextAID + * @param pin + * @throws at.gv.egiz.smcc.SignatureCardException + */ + private void activatePIN(byte kid, byte[] contextAID, byte[] pin) throws SignatureCardException { + try { + Card icc = card.getCard(); + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + if (contextAID != null) { + CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); + ResponseAPDU responseAPDU = channel.transmit(selectAPDU); + if (responseAPDU.getSW() != 0x9000) { + 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); + } + } + + if (pin.length > 7) { + log.error("Invalid PIN"); + throw new SignatureCardException("Invalid PIN"); + } + byte length = (byte) (0x20 | pin.length * 2); + + byte[] apdu = new byte[]{ + (byte) 0x00, (byte) 0x24, (byte) 0x01, kid, (byte) 0x08, + (byte) length, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; + for (int i = 0; i < pin.length; i++) { + apdu[i + 6] = pin[i]; + } + + CommandAPDU verifyAPDU = new CommandAPDU(apdu); + ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); + + if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); + log.error(msg); + throw new SignatureCardException(msg); + } + + + icc.endExclusive(); + + + } catch (CardException ex) { + log.error("Failed to get PIN status: " + ex.getMessage()); + throw new SignatureCardException("Failed to get PIN status", ex); + } + } + + private void changePIN(byte kid, byte[] contextAID, byte[] oldPIN, byte[] newPIN) throws SignatureCardException { + try { + Card icc = card.getCard(); + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + if (contextAID != null) { + CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); + ResponseAPDU responseAPDU = channel.transmit(selectAPDU); + if (responseAPDU.getSW() != 0x9000) { + String msg = "Failed to change PIN " + SMCCHelper.toString(new byte[]{kid}) + + ": Failed to select AID " + SMCCHelper.toString(contextAID) + + ": " + SMCCHelper.toString(responseAPDU.getBytes()); + log.error(msg); + throw new SignatureCardException(msg); + } + } + + if (oldPIN.length > 7 || newPIN.length > 7) { + log.error("Invalid PIN"); + throw new SignatureCardException("Invalid PIN"); + } + byte oldLength = (byte) (0x20 | oldPIN.length * 2); + byte newLength = (byte) (0x20 | newPIN.length * 2); + + byte[] apdu = new byte[]{ + (byte) 0x00, (byte) 0x24, (byte) 0x00, kid, (byte) 0x10, + oldLength, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + newLength, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; + for (int i = 0; i < oldPIN.length; i++) { + apdu[i + 6] = oldPIN[i]; + } + for (int i = 0; i < newPIN.length; i++) { + apdu[i + 14] = newPIN[i]; + } + + CommandAPDU verifyAPDU = new CommandAPDU(apdu); + ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); + + 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); + } + + + icc.endExclusive(); + + + } catch (CardException ex) { + log.error("Failed to get PIN status: " + ex.getMessage()); + throw new SignatureCardException("Failed to get PIN status", ex); + } + } + + public Map getPINStatuses() throws SignatureCardException { + try { + Card icc = card.getCard(); + icc.beginExclusive(); + CardChannel channel = icc.getBasicChannel(); + + HashMap pinStatuses = new HashMap(); + List pins = card.getPINSpecs(); + + //select DF_SichereSignatur 00 A4 04 0C 08 D0 40 00 00 17 00 12 01 +// CommandAPDU selectAPDU = new CommandAPDU(new byte[]{(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x0c, (byte) 0x08, +// (byte) 0xd0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x12, (byte) 0x01}); +// ResponseAPDU rAPDU = channel.transmit(selectAPDU); +// log.debug("SELECT FILE DF_SichereSignatur: " + SMCCHelper.toString(rAPDU.getBytes())); + + //select DF_SIG DF 70 +// CommandAPDU selectAPDU = new CommandAPDU(new byte[]{(byte) 0x00, (byte) 0xa4, (byte) 0x00, (byte) 0x0c, (byte) 0x02, +// (byte) 0xdf, (byte) 0x70 }); +// ResponseAPDU rAPDU = channel.transmit(selectAPDU); +// log.debug("SELECT FILE DF_SIG: " + SMCCHelper.toString(rAPDU.getBytes())); + + //select DF_DEC DF 71 +// CommandAPDU selectAPDU = new CommandAPDU(new byte[]{(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x0c, (byte) 0x08, +// (byte) 0xd0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x12, (byte) 0x01}); +// ResponseAPDU rAPDU = channel.transmit(selectAPDU); +// log.debug("SELECT FILE DF_SichereSignatur: " + SMCCHelper.toString(rAPDU.getBytes())); + + 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) { + 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); + } + } + + 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())); + } + + pinStatuses.put(pinSpec, status); + } + icc.endExclusive(); + + return pinStatuses; + + } catch (CardException ex) { + log.error("Failed to get PIN status: " + ex.getMessage()); + throw new SignatureCardException("Failed to get PIN status", ex); + } + } + + private byte[] encodePIN(char[] pinChars) { + int length = (int) Math.ceil(pinChars.length/2); + byte[] pin = new byte[length]; + for (int i = 0; i < length; i++) { + pin[i] = (byte) (16*Character.digit(pinChars[i*2], 16) + Character.digit(pinChars[i*2+1], 16)); + } + log.trace("***** " + SMCCHelper.toString(pin) + " ******"); + return pin; + } + + 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[]{"FAILED TO GET PIN STATUSES: " + ex.getMessage()}, + this, "cancel"); + } + } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java deleted file mode 100644 index b2d34ff2..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java +++ /dev/null @@ -1,93 +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.bku.gui.PINStatusProvider; -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.ActivatePINRequest; -import at.gv.egiz.stal.ext.ChangePINRequest; -import at.gv.egiz.stal.ext.UnblockPINRequest; -import java.util.logging.Level; -import java.util.logging.Logger; -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; - -/** - * - * @author Clemens Orthacker - */ -public class PINMgmtRequestHandler extends AbstractRequestHandler implements PINStatusProvider { - - protected static final Log log = LogFactory.getLog(PINMgmtRequestHandler.class); - - @Override - public STALResponse handleRequest(STALRequest request) throws InterruptedException { - if (request instanceof ActivatePINRequest) { - log.error("not implemented yet"); - return new ErrorResponse(1000); - - } else if (request instanceof ChangePINRequest) { - log.error("not implemented yet"); - return new ErrorResponse(1000); - - } else if (request instanceof UnblockPINRequest) { - log.error("not implemented yet"); - return new ErrorResponse(1000); - - } else { - log.error("Got unexpected STAL request: " + request); - return new ErrorResponse(1000); - } - } - - @Override - public boolean requireCard() { - return true; - } - - @Override - public STATUS getPINStatus(int pin) throws SignatureCardException { - try { - Card icc = card.getCard(); - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); - CommandAPDU verifyAPDU = new CommandAPDU(new byte[] {(byte) 0x00} ); - ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); - byte sw1 = (byte) responseAPDU.getSW1(); - byte[] sw = new byte[] { - (byte) (0xFF & responseAPDU.getSW1()), - (byte) (0xFF & responseAPDU.getSW2()) }; - - icc.endExclusive(); - return STATUS.ACTIV; - } catch (CardException ex) { - log.error("Failed to get PIN status: " + ex.getMessage()); - throw new SignatureCardException("Failed to get PIN status", ex); - } - } - -} 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 469af15f..e51044af 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 @@ -15,10 +15,34 @@ title.activation=Aktivierung title.pin.mgmt=PIN Verwaltung -message.pin.mgmt=under construction +title.activate.pin=PIN Aktivieren +title.change.pin=PIN \u00C4ndern +title.unblock.pin=PIN Entsperren + +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 + label.activation=e-card Aktivierungsprozess label.activation.step=Schritt {0} label.activation.idle=Warte auf Server... +label.old.pin=Alte {0}: +label.new.pin=Neue {0}: +label.repeat.pin=Best\u00E4tigung: + button.activate=Aktivieren button.change=\u00C4ndern -button.unblock=Entsperren \ No newline at end of file +button.unblock=Entsperren + +help.activation=help.activation +help.pin.mgmt=help.pin.mgmt + +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. + +status.not.active=NICHT AKTIV +status.active=AKTIV +status.blocked=GESPERRT +status.unknown=UNBEKANNT 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 16ac7d0b..1cf4a102 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 @@ -13,12 +13,36 @@ # See the License for the specific language governing permissions and # limitations under the License. -title.activation=Aktivation +title.activation=Activation title.pin.mgmt=PIN Management -message.pin.mgmt=under construction +title.activate.pin=Activate PIN +title.change.pin=Change PIN +title.unblock.pin=Unblock PIN + +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} + label.activation=e-card activation process label.activation.step=Step {0} label.activation.idle=Wait for server... +label.old.pin=Old {0}: +label.new.pin=New {0}: +label.repeat.pin=Confirmation: + button.activate=Activate button.change=Change -button.unblock=Unblock \ No newline at end of file +button.unblock=Unblock + +help.activation=help.activation +help.pin.mgmt=help.pin.mgmt + +err.activate=An error occured during activation of {0}. +err.change=An error occured during changing of {0}. +err.unblock=Unblocking of {0} is not supported. + +status.not.active=Not active +status.active=Active +status.blocked=Blocked +status.unknown=Unknown 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 669a63fc..ef8c87e4 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 @@ -25,8 +25,6 @@ import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.impl.ByteArrayHashDataInput; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.ByteArrayInputStream; -import java.io.InputStream; import java.util.ArrayList; import java.util.List; @@ -46,7 +44,7 @@ public class BKUGUIWorker implements Runnable { public void run() { try { - final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN"); + final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN", (byte)0x00, null); final ActionListener cancelListener = new ActionListener() { diff --git a/BKUAppletExt/src/test/resources/appletTest.html b/BKUAppletExt/src/test/resources/appletTest.html index 9add4309..813ee1f0 100644 --- a/BKUAppletExt/src/test/resources/appletTest.html +++ b/BKUAppletExt/src/test/resources/appletTest.html @@ -19,7 +19,7 @@
+ width=270 height=180> 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 f564c07a..1d5a2cf4 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,9 +38,6 @@ 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; import javax.swing.JButton; @@ -51,7 +48,6 @@ import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JScrollPane; import javax.swing.JTable; -import javax.swing.JTextField; import javax.swing.LayoutStyle; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; @@ -1064,7 +1060,9 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public char[] getPin() { if (pinField != null) { - return pinField.getPassword(); + char[] pin = pinField.getPassword(); + pinField = null; + return pin; } return 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 2054ae86..87b636f0 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 @@ -22,6 +22,7 @@ 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; /** @@ -30,9 +31,10 @@ import javax.swing.text.PlainDocument; */ class PINDocument extends PlainDocument { - private PINSpec pinSpec; - private Pattern pinPattern; - private JButton enterButton; + protected PINSpec pinSpec; + protected Pattern pinPattern; + protected JButton enterButton; + protected Document compareTo; public PINDocument(PINSpec pinSpec, JButton enterButton) { this.pinSpec = pinSpec; @@ -44,6 +46,11 @@ class PINDocument extends PlainDocument { this.enterButton = enterButton; } + public PINDocument(PINSpec pinSpec, JButton enterButton, Document compareTo) { + this(pinSpec, enterButton); + this.compareTo = compareTo; + } + @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { if (pinSpec.getMaxLength() < 0 || pinSpec.getMaxLength() >= (getLength() + str.length())) { @@ -58,12 +65,23 @@ class PINDocument extends PlainDocument { super.insertString(offs, str, a); } } - enterButton.setEnabled(getLength() >= pinSpec.getMinLength()); + if (enterButton != null) { + enterButton.setEnabled(getLength() >= pinSpec.getMinLength() && compare()); + } } @Override public void remove(int offs, int len) throws BadLocationException { super.remove(offs, len); - enterButton.setEnabled(getLength() >= pinSpec.getMinLength()); + if (enterButton != null) { + enterButton.setEnabled(getLength() >= pinSpec.getMinLength() && 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/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 8436a730..1e0bc9f5 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,7 +20,7 @@ title.cardnotsupported=Die Karte wird nicht unterst\u00FCtzt title.cardpin=Karte wird gelesen title.sign=Signatur erstellen title.error=Fehler -title.retry=Falscher PIN +title.retry=Falsche PIN title.wait=Bitte warten title.hashdata=Signaturdaten windowtitle.save=Signaturdaten speichern @@ -84,7 +84,7 @@ help.cardnotsupported=Nicht unterst\u00FCtzte B\u00FCrgerkarte help.insertcard=Keine B\u00FCrgerkarte im Kartenleser help.cardpin=Pineingabe help.signpin=Signatur-Pineingabe -help.retry=Falscher Pin +help.retry=Falsche Pin help.hashdata=Signierte Inhalte help.hashdatalist=Signierte Inhalte help.hashdataviewer=Anzeige signierter Inhalte \ 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 73aaab46..08ecaa7f 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 @@ -46,7 +46,7 @@ public class BKUGUIWorker implements Runnable { public void run() { // try { - final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN"); + final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN", (byte) 0x81, null); final ActionListener cancelListener = new ActionListener() { diff --git a/STALExt/src/main/java/at/gv/egiz/stal/ext/ActivatePINRequest.java b/STALExt/src/main/java/at/gv/egiz/stal/ext/ActivatePINRequest.java deleted file mode 100644 index f2039388..00000000 --- a/STALExt/src/main/java/at/gv/egiz/stal/ext/ActivatePINRequest.java +++ /dev/null @@ -1,28 +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.ext; - -import at.gv.egiz.stal.STALRequest; - -/** - * - * @author Clemens Orthacker - */ -public class ActivatePINRequest extends STALRequest { - -} diff --git a/STALExt/src/main/java/at/gv/egiz/stal/ext/ChangePINRequest.java b/STALExt/src/main/java/at/gv/egiz/stal/ext/ChangePINRequest.java deleted file mode 100644 index ea508146..00000000 --- a/STALExt/src/main/java/at/gv/egiz/stal/ext/ChangePINRequest.java +++ /dev/null @@ -1,28 +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.ext; - -import at.gv.egiz.stal.STALRequest; - -/** - * - * @author Clemens Orthacker - */ -public class ChangePINRequest extends STALRequest { - -} diff --git a/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementRequest.java b/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementRequest.java new file mode 100644 index 00000000..87c53e24 --- /dev/null +++ b/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementRequest.java @@ -0,0 +1,31 @@ +/* + * 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.ext; + +import at.gv.egiz.stal.STALRequest; + +/** + * Dummy STAL request to trigger PIN Management. (no proper STAL requests + * for PIN activation, unblocking) + * + * + * @author Clemens Orthacker + */ +public class PINManagementRequest extends STALRequest { + +} diff --git a/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementResponse.java b/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementResponse.java new file mode 100644 index 00000000..b8b90604 --- /dev/null +++ b/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementResponse.java @@ -0,0 +1,28 @@ +/* + * 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.ext; + +import at.gv.egiz.stal.STALResponse; + +/** + * + * @author Clemens Orthacker + */ +public class PINManagementResponse extends STALResponse { + +} diff --git a/STALExt/src/main/java/at/gv/egiz/stal/ext/UnblockPINRequest.java b/STALExt/src/main/java/at/gv/egiz/stal/ext/UnblockPINRequest.java deleted file mode 100644 index 543de31c..00000000 --- a/STALExt/src/main/java/at/gv/egiz/stal/ext/UnblockPINRequest.java +++ /dev/null @@ -1,28 +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.ext; - -import at.gv.egiz.stal.STALRequest; - -/** - * - * @author Clemens Orthacker - */ -public class UnblockPINRequest extends STALRequest { - -} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java index ae4918ce..b64306aa 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java @@ -14,98 +14,105 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.bku.slcommands.impl.xsect; - -import iaik.xml.crypto.dom.DOMCryptoContext; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.SequenceInputStream; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; +package at.gv.egiz.bku.slcommands.impl.xsect; + +import iaik.xml.crypto.dom.DOMCryptoContext; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.SequenceInputStream; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.crypto.MarshalException; -import javax.xml.crypto.dom.DOMStructure; -import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.crypto.dsig.DigestMethod; -import javax.xml.crypto.dsig.Reference; -import javax.xml.crypto.dsig.Transform; -import javax.xml.crypto.dsig.XMLObject; -import javax.xml.crypto.dsig.spec.TransformParameterSpec; -import javax.xml.crypto.dsig.spec.XPathFilter2ParameterSpec; -import javax.xml.crypto.dsig.spec.XPathType; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.DOMConfiguration; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.DocumentFragment; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.Text; -import org.w3c.dom.bootstrap.DOMImplementationRegistry; -import org.w3c.dom.ls.DOMImplementationLS; -import org.w3c.dom.ls.LSException; -import org.w3c.dom.ls.LSInput; -import org.w3c.dom.ls.LSOutput; -import org.w3c.dom.ls.LSParser; -import org.w3c.dom.ls.LSSerializer; - -import at.buergerkarte.namespaces.securitylayer._1.Base64XMLLocRefOptRefContentType; -import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; -import at.buergerkarte.namespaces.securitylayer._1.MetaInfoType; -import at.buergerkarte.namespaces.securitylayer._1.TransformsInfoType; -import at.gv.egiz.bku.binding.HttpUtil; -import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.bku.slexceptions.SLRequestException; -import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.spec.TransformParameterSpec; +import javax.xml.crypto.dsig.spec.XPathFilter2ParameterSpec; +import javax.xml.crypto.dsig.spec.XPathType; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3._2000._09.xmldsig_.TransformType; +import org.w3._2000._09.xmldsig_.TransformsType; +import org.w3c.dom.DOMConfiguration; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.Text; +import org.w3c.dom.bootstrap.DOMImplementationRegistry; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSException; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSOutput; +import org.w3c.dom.ls.LSParser; +import org.w3c.dom.ls.LSSerializer; + +import at.buergerkarte.namespaces.securitylayer._1.Base64XMLLocRefOptRefContentType; +import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; +import at.buergerkarte.namespaces.securitylayer._1.MetaInfoType; +import at.buergerkarte.namespaces.securitylayer._1.TransformsInfoType; +import at.gv.egiz.bku.binding.HttpUtil; +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.bku.slexceptions.SLViewerException; -import at.gv.egiz.bku.utils.urldereferencer.StreamData; -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.bku.utils.urldereferencer.StreamData; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; import at.gv.egiz.bku.viewer.ValidationException; import at.gv.egiz.bku.viewer.Validator; import at.gv.egiz.bku.viewer.ValidatorFactory; -import at.gv.egiz.dom.DOMUtils; -import at.gv.egiz.slbinding.impl.XMLContentType; - -/** - * This class represents a DataObject of an XML-Signature - * created by the security layer command CreateXMLSignature. - * - * @author mcentner - */ -public class DataObject { - - /** - * Logging facility. - */ - private static Log log = LogFactory.getLog(DataObject.class); - - /** - * DOM Implementation. - */ - private static final String DOM_LS_3_0 = "LS 3.0"; - - /** - * The array of the default preferred MIME type order. - */ - private static final String[] DEFAULT_PREFFERED_MIME_TYPES = - new String[] { +import at.gv.egiz.dom.DOMUtils; +import at.gv.egiz.marshal.NamespacePrefix; +import at.gv.egiz.marshal.NamespacePrefixMapperImpl; +import at.gv.egiz.slbinding.impl.XMLContentType; +import javax.xml.namespace.NamespaceContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +/** + * This class represents a DataObject of an XML-Signature + * created by the security layer command CreateXMLSignature. + * + * @author mcentner + */ +public class DataObject { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(DataObject.class); + + /** + * DOM Implementation. + */ + private static final String DOM_LS_3_0 = "LS 3.0"; + + /** + * The array of the default preferred MIME type order. + */ + private static final String[] DEFAULT_PREFFERED_MIME_TYPES = + new String[] { "text/plain", - "application/xhtml+xml" + "application/xhtml+xml" }; /** @@ -149,87 +156,87 @@ public class DataObject { validMimeTypes = mediaTypes; } - /** - * The DOM implementation used. - */ - private DOMImplementationLS domImplLS; - - /** - * The signature context. - */ - private SignatureContext ctx; - - /** - * The Reference for this DataObject. - */ - private XSECTReference reference; - - /** - * The XMLObject for this DataObject. - */ - private XMLObject xmlObject; - - /** - * The MIME-Type of the digest input. - */ - private String mimeType; - - /** - * An optional description of the digest input. - */ - private String description; - - /** - * Creates a new instance. - * - * @param document the document of the target signature - */ - public DataObject(SignatureContext signatureContext) { - this.ctx = signatureContext; - - DOMImplementationRegistry registry; - try { - registry = DOMImplementationRegistry.newInstance(); - } catch (Exception e) { - log.error("Failed to get DOMImplementationRegistry.", e); - throw new SLRuntimeException("Failed to get DOMImplementationRegistry."); - } - - domImplLS = (DOMImplementationLS) registry.getDOMImplementation(DOM_LS_3_0); - if (domImplLS == null) { - log.error("Failed to get DOMImplementation " + DOM_LS_3_0); - throw new SLRuntimeException("Failed to get DOMImplementation " + DOM_LS_3_0); - } - - } - - /** - * @return the reference - */ - public Reference getReference() { - return reference; - } - - /** - * @return the xmlObject - */ - public XMLObject getXmlObject() { - return xmlObject; - } - - /** - * @return the mimeType - */ - public String getMimeType() { - return mimeType; - } - - /** - * @return the description - */ - public String getDescription() { - return description; - } + /** + * The DOM implementation used. + */ + private DOMImplementationLS domImplLS; + + /** + * The signature context. + */ + private SignatureContext ctx; + + /** + * The Reference for this DataObject. + */ + private XSECTReference reference; + + /** + * The XMLObject for this DataObject. + */ + private XMLObject xmlObject; + + /** + * The MIME-Type of the digest input. + */ + private String mimeType; + + /** + * An optional description of the digest input. + */ + private String description; + + /** + * Creates a new instance. + * + * @param document the document of the target signature + */ + public DataObject(SignatureContext signatureContext) { + this.ctx = signatureContext; + + DOMImplementationRegistry registry; + try { + registry = DOMImplementationRegistry.newInstance(); + } catch (Exception e) { + log.error("Failed to get DOMImplementationRegistry.", e); + throw new SLRuntimeException("Failed to get DOMImplementationRegistry."); + } + + domImplLS = (DOMImplementationLS) registry.getDOMImplementation(DOM_LS_3_0); + if (domImplLS == null) { + log.error("Failed to get DOMImplementation " + DOM_LS_3_0); + throw new SLRuntimeException("Failed to get DOMImplementation " + DOM_LS_3_0); + } + + } + + /** + * @return the reference + */ + public Reference getReference() { + return reference; + } + + /** + * @return the xmlObject + */ + public XMLObject getXmlObject() { + return xmlObject; + } + + /** + * @return the mimeType + */ + public String getMimeType() { + return mimeType; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } public void validateHashDataInput() throws SLViewerException { @@ -293,823 +300,920 @@ public class DataObject { } } - - /** - * Configures this DataObject with the information provided within the given - * sl:DataObjectInfo. - * - * @param dataObjectInfo - * the sl:DataObjectInfo - * - * @throws SLCommandException - * if configuring this DataObject with the information provided in - * the sl:DataObjectInfo fails. - * @throws SLRequestException - * if the information provided in the sl:DataObjectInfo - * does not conform to the security layer specification. - * @throws NullPointerException - * if dataObjectInfo is null - */ - public void setDataObjectInfo(DataObjectInfoType dataObjectInfo) throws SLCommandException, SLRequestException { - - Base64XMLLocRefOptRefContentType dataObject = dataObjectInfo.getDataObject(); - String structure = dataObjectInfo.getStructure(); - - // select and unmarshal an appropriate transformation path if provided - // and set the final data meta information - XSECTTransforms transforms = createTransformsAndSetFinalDataMetaInfo(dataObjectInfo.getTransformsInfo()); - - if ("enveloping".equals(structure)) { - - // configure this DataObject as an enveloped DataObject - setEnvelopedDataObject(dataObject, transforms); - - } else if ("detached".equals(structure)) { - - // configure this DataObject as an detached DataObject - setDetachedDataObject(dataObject, transforms); - - } - // other values are not allowed by the schema and are therefore ignored - - } - - /** - * Configures this DataObject as an enveloped DataObject with the information - * provided within the given sl:DataObject. - * - * @param dataObject - * the sl:DataObject - * @param transforms - * an optional Transforms element (may be - * null) - * - * @throws SLCommandException - * if configuring this DataObject with the information provided in - * the sl:DataObject fails. - * @throws SLRequestException - * if the information provided in the sl:DataObject - * does not conform to the security layer specification. - * @throws NullPointerException - * if dataObject is null - */ - private void setEnvelopedDataObject( - Base64XMLLocRefOptRefContentType dataObject, XSECTTransforms transforms) - throws SLCommandException, SLRequestException { - - String reference = dataObject.getReference(); - if (reference == null) { - // - // case A - // - // The Reference attribute is not used; the content of sl:DataObject represents the data object. - // If the data object is XML-coded (the sl:XMLContent element is used in sl:DataObject), then it - // must be incorporated in the signature structure as parsed XML. - // - - if (dataObject.getBase64Content() != null) { - - log.debug("Adding DataObject (Base64Content) without a reference URI."); - - // create XMLObject - XMLObject xmlObject = createXMLObject(new ByteArrayInputStream(dataObject.getBase64Content())); - - setXMLObjectAndReferenceBase64(xmlObject, transforms); - - } else if (dataObject.getXMLContent() != null) { - - log.debug("Adding DataObject (XMLContent) without a reference URI."); - - // create XMLObject - DocumentFragment content = parseDataObject((XMLContentType) dataObject.getXMLContent()); - XMLObject xmlObject = createXMLObject(content); - - setXMLObjectAndReferenceXML(xmlObject, transforms); - - } else if (dataObject.getLocRefContent() != null) { - - log.debug("Adding DataObject (LocRefContent) without a reference URI."); - - setEnvelopedDataObject(dataObject.getLocRefContent(), transforms); - - } else { - - // not allowed - log.info("XML structure of the command request contains an " + - "invalid combination of optional elements or attributes. " + - "DataObject of structure='enveloped' without a reference must contain content."); - throw new SLRequestException(3003); - - } - - } else { - - if (dataObject.getBase64Content() == null && - dataObject.getXMLContent() == null && - dataObject.getLocRefContent() == null) { - - // - // case B - // - // The Reference attribute contains a URI that must be resolved by the - // Citizen Card Environment to obtain the data object. - // The content of sl:DataObject remains empty - // - - log.debug("Adding DataObject from reference URI '" + reference + "'."); - - setEnvelopedDataObject(reference, transforms); - - } else { - - // not allowed - log.info("XML structure of the command request contains an " + - "invalid combination of optional elements or attributes. " + - "DataObject of structure='enveloped' with reference must not contain content."); - throw new SLRequestException(3003); - - } - - - } - - } - - /** - * Configures this DataObject as an enveloped DataObject with the content to - * be dereferenced from the given reference. - * - * @param reference - * the reference URI - * @param transforms - * an optional Transforms element (may be - * null) - * - * @throws SLCommandException - * if dereferencing the given reference fails, or if - * configuring this DataObject with the data dereferenced from the - * given reference fails. - * @throws NullPointerException - * if reference is null - */ - private void setEnvelopedDataObject(String reference, XSECTTransforms transforms) throws SLCommandException { - - if (reference == null) { - throw new NullPointerException("Argument 'reference' must not be null."); - } - - // dereference URL - URLDereferencer dereferencer = URLDereferencer.getInstance(); - - StreamData streamData; - try { - streamData = dereferencer.dereference(reference, ctx.getDereferencerContext()); - } catch (IOException e) { - log.info("Failed to dereference XMLObject from '" + reference + "'.", e); - throw new SLCommandException(4110); - } - - Node childNode; - - String contentType = streamData.getContentType(); - if (contentType.startsWith("text/xml")) { - - // If content type is text/xml parse content. - String charset = HttpUtil.getCharset(contentType, true); - - Document doc = parseDataObject(streamData.getStream(), charset); - - childNode = doc.getDocumentElement(); - - if (childNode == null) { - log.info("Failed to parse XMLObject from '" + reference + "'."); - throw new SLCommandException(4111); - } - - XMLObject xmlObject = createXMLObject(childNode); - - setXMLObjectAndReferenceXML(xmlObject, transforms); - - } else { - - // Include content Base64 encoded. - XMLObject xmlObject = createXMLObject(streamData.getStream()); - - setXMLObjectAndReferenceBase64(xmlObject, transforms); - - } - - } - - /** - * Configures this DataObject as an detached DataObject with the information - * provided in the given sl:DataObject and optionally - * transforms. - * - * @param dataObject - * the sl:DataObject - * @param transforms - * an optional Transforms object, may be null - * - * @throws SLCommandException - * if configuring this DataObject with the information provided in - * the sl:DataObject fails. - * @throws SLRequestException - * if the information provided in the sl:DataObject - * does not conform to the security layer specification. - * @throws NullPointerException - * if dataObject is null - */ - private void setDetachedDataObject( - Base64XMLLocRefOptRefContentType dataObject, XSECTTransforms transforms) - throws SLCommandException, SLRequestException { - - String referenceURI = dataObject.getReference(); - - if (referenceURI == null) { - - // not allowed - log.info("XML structure of the command request contains an " + - "invalid combination of optional elements or attributes. " + - "DataObject of structure='detached' must contain a reference."); - throw new SLRequestException(3003); - - } else { - - DigestMethod dm; - try { - dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); - } catch (NoSuchAlgorithmException e) { - log.error("Failed to get DigestMethod.", e); - throw new SLCommandException(4006); - } catch (InvalidAlgorithmParameterException e) { - log.error("Failed to get DigestMethod.", e); - throw new SLCommandException(4006); - } - - String idValue = ctx.getIdValueFactory().createIdValue("Reference"); - - reference = new XSECTReference(referenceURI, dm, transforms, null, idValue); - - // case D: - // - // The Reference attribute contains a URI that is used by the Citizen Card - // Environment to code the reference to the data object as part of the XML - // signature (attribute URI in the dsig:Reference) element. The content of - // sl:DataObject represents the data object. - - if (dataObject.getLocRefContent() != null) { - String locRef = dataObject.getLocRefContent(); - try { - this.reference.setDereferencer(new LocRefDereferencer(ctx.getDereferencerContext(), locRef)); - } catch (URISyntaxException e) { - log.info("Invalid URI '" + locRef + "' in DataObject.", e); - throw new SLCommandException(4003); - } catch (IllegalArgumentException e) { - log.info("LocRef URI of '" + locRef + "' not supported in DataObject. ", e); - throw new SLCommandException(4003); - } - } else if (dataObject.getBase64Content() != null) { - byte[] base64Content = dataObject.getBase64Content(); - this.reference.setDereferencer(new ByteArrayDereferencer(base64Content)); - } else if (dataObject.getXMLContent() != null) { - XMLContentType xmlContent = (XMLContentType) dataObject.getXMLContent(); - byte[] bytes = xmlContent.getRedirectedStream().toByteArray(); - this.reference.setDereferencer(new ByteArrayDereferencer(bytes)); - } else { - - // case C: - // - // The Reference attribute contains a URI that must be resolved by the - // Citizen Card Environment to obtain the data object. The Reference - // attribute contains a URI that is used by the Citizen Card Environment - // to code the reference to the data object as part of the XML signature - // (attribute URI in the dsig:Reference) element. The content of - // sl:DataObject remains empty. - - } - - } - } - - /** - * Returns the preferred sl:TransformInfo from the given list of - * transformInfos, or null if none of the given - * transformInfos is preferred over the others. - * - * @param transformsInfos - * a list of sl:TransformInfos - * - * @return the selected sl:TransformInfo or null, if - * none is preferred over the others - */ - private TransformsInfoType selectPreferredTransformsInfo(List transformsInfos) { - - Map mimeTypes = new HashMap(); - - StringBuilder debugString = null; - if (log.isDebugEnabled()) { - debugString = new StringBuilder(); - debugString.append("Got " + transformsInfos.size() + " TransformsInfo(s):"); - } - - for (TransformsInfoType transformsInfoType : transformsInfos) { - MetaInfoType finalDataMetaInfo = transformsInfoType.getFinalDataMetaInfo(); - String mimeType = finalDataMetaInfo.getMimeType(); - String description = finalDataMetaInfo.getDescription(); - mimeTypes.put(mimeType, transformsInfoType); - if (debugString != null) { - debugString.append("\n FinalDataMetaInfo: MIME-Type="); - debugString.append(mimeType); - if (description != null) { - debugString.append(" "); - debugString.append(description); - } - } - } - - if (debugString != null) { - log.debug(debugString); - } - - // look for preferred transform - for (String mimeType : DEFAULT_PREFFERED_MIME_TYPES) { - if (mimeTypes.containsKey(mimeType)) { - return mimeTypes.get(mimeType); - } - } - - // no preferred transform - return null; - - } - - /** - * Create an instance of ds:Transforms from the given - * sl:TransformsInfo. - * - * @param transformsInfo - * the sl:TransformsInfo - * - * @return a corresponding unmarshalled ds:Transforms, or - * null if the given sl:TransformsInfo does - * not contain a dsig:Transforms element - * - * @throws SLRequestException - * if the ds:Transforms in the given - * transformsInfo are not valid or cannot be parsed. - * - * @throws MarshalException - * if the ds:Transforms in the given - * transformsInfo cannot be unmarshalled. - */ - private XSECTTransforms createTransforms(TransformsInfoType transformsInfo) throws SLRequestException, MarshalException { - - ByteArrayOutputStream redirectedStream = ((at.gv.egiz.slbinding.impl.TransformsInfoType) transformsInfo).getRedirectedStream(); - byte[] transformBytes = (redirectedStream != null) ? redirectedStream.toByteArray() : null; - - if (transformBytes != null && transformBytes.length > 0) { - - // debug - if (log.isTraceEnabled()) { - StringBuilder sb = new StringBuilder(); - sb.append("Trying to parse transforms:\n"); - sb.append(new String(transformBytes, Charset.forName("UTF-8"))); - log.trace(sb); - } - - DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS(); - LSInput input = domImplLS.createLSInput(); - input.setByteStream(new ByteArrayInputStream(transformBytes)); - - LSParser parser = domImplLS.createLSParser( - DOMImplementationLS.MODE_SYNCHRONOUS, null); - DOMConfiguration domConfig = parser.getDomConfig(); - SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); - domConfig.setParameter("error-handler", errorHandler); - domConfig.setParameter("validate", Boolean.FALSE); - - Document document; - try { - document = parser.parse(input); - } catch (DOMException e) { - log.info("Failed to parse dsig:Transforms.", e); - throw new SLRequestException(3002); - } catch (LSException e) { - log.info("Failed to parse dsig:Transforms.", e); - throw new SLRequestException(3002); - } - - // adopt ds:Transforms - Element documentElement = document.getDocumentElement(); - Node adoptedTransforms = ctx.getDocument().adoptNode(documentElement); - - DOMCryptoContext context = new DOMCryptoContext(); - - // unmarshall ds:Transforms - return new XSECTTransforms(context, adoptedTransforms); - - } else { - return null; - } - - } - - /** - * Sets the mimeType and the description value - * for this DataObject. - * - * @param metaInfoType the sl:FinalMetaDataInfo - * - * @throws NullPointerException if metaInfoType is null - */ - private void setFinalDataMetaInfo(MetaInfoType metaInfoType) { - - this.mimeType = metaInfoType.getMimeType(); - this.description = metaInfoType.getDescription(); - - } - - /** - * Selects an appropriate transformation path (if present) from the given list - * of sl:TransformInfos, sets the corresponding final data meta info and - * returns the corresponding unmarshalled ds:Transforms. - * - * @param transformsInfos the sl:TransformInfos - * - * @return the unmarshalled ds:Transforms, or null if - * no transformation path has been selected. - * - * @throws SLRequestException if the given list ds:TransformsInfo contains - * an invalid ds:Transforms element, or no suitable transformation path - * can be found. - */ - private XSECTTransforms createTransformsAndSetFinalDataMetaInfo( - List transformsInfos) throws SLRequestException { - - TransformsInfoType preferredTransformsInfo = selectPreferredTransformsInfo(transformsInfos); - // try preferred transform - if (preferredTransformsInfo != null) { - - try { - XSECTTransforms transforms = createTransforms(preferredTransformsInfo); - setFinalDataMetaInfo(preferredTransformsInfo.getFinalDataMetaInfo()); - return transforms; - } catch (MarshalException e) { - - String mimeType = preferredTransformsInfo.getFinalDataMetaInfo().getMimeType(); - log.info("Failed to unmarshal preferred transformation path (MIME-Type=" - + mimeType + ").", e); - - } - - } - - // look for another suitable transformation path - for (TransformsInfoType transformsInfoType : transformsInfos) { - - try { - XSECTTransforms transforms = createTransforms(transformsInfoType); - setFinalDataMetaInfo(transformsInfoType.getFinalDataMetaInfo()); - return transforms; - } catch (MarshalException e) { - - String mimeType = transformsInfoType.getFinalDataMetaInfo().getMimeType(); - log.info("Failed to unmarshal transformation path (MIME-Type=" - + mimeType + ").", e); - } - - } - - // no suitable transformation path found - throw new SLRequestException(3003); - - } - - /** - * Create an XMLObject with the Base64 encoding of the given - * content. - * - * @param content - * the to-be Base64 encoded content - * @return an XMLObject with the Base64 encoded content - */ - private XMLObject createXMLObject(InputStream content) { - - Text textNode; - try { - textNode = at.gv.egiz.dom.DOMUtils.createBase64Text(content, ctx.getDocument()); - } catch (IOException e) { - log.error(e); - throw new SLRuntimeException(e); - } - - DOMStructure structure = new DOMStructure(textNode); - - String idValue = ctx.getIdValueFactory().createIdValue("Object"); - - return ctx.getSignatureFactory().newXMLObject(Collections.singletonList(structure), idValue, null, null); - - } - - /** - * Create an XMLObject with the given content node. - * - * @param content the content node - * - * @return an XMLObject with the given content - */ - private XMLObject createXMLObject(Node content) { - - String idValue = ctx.getIdValueFactory().createIdValue("Object"); - - List structures = Collections.singletonList(new DOMStructure(content)); - - return ctx.getSignatureFactory().newXMLObject(structures, idValue, null, null); - - } - - /** - * Sets the given xmlObject and creates and sets a corresponding - * Reference. - *

- * A transform to Base64-decode the xmlObject's content is inserted at the top - * of to the optional transforms if given, or to a newly created - * Transforms element if transforms is - * null. - * - * @param xmlObject - * the XMLObject - * @param transforms - * an optional Transforms element (may be - * null) - * - * @throws SLCommandException - * if creating the Reference fails - * @throws NullPointerException - * if xmlObject is null - */ - private void setXMLObjectAndReferenceBase64(XMLObject xmlObject, XSECTTransforms transforms) throws SLCommandException { - - // create reference URI - // - // NOTE: the ds:Object can be referenced directly, as the Base64 transform - // operates on the text() of the input nodelist. - // - String referenceURI = "#" + xmlObject.getId(); - - // create Base64 Transform - Transform transform; - try { - transform = ctx.getSignatureFactory().newTransform(Transform.BASE64, (TransformParameterSpec) null); - } catch (NoSuchAlgorithmException e) { - // algorithm must be present - throw new SLRuntimeException(e); - } catch (InvalidAlgorithmParameterException e) { - // algorithm does not take parameters - throw new SLRuntimeException(e); - } - - if (transforms == null) { - transforms = new XSECTTransforms(Collections.singletonList(transform)); - } else { - transforms.insertTransform(transform); - } - - DigestMethod dm; - try { - dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); - } catch (NoSuchAlgorithmException e) { - log.error("Failed to get DigestMethod.", e); - throw new SLCommandException(4006); - } catch (InvalidAlgorithmParameterException e) { - log.error("Failed to get DigestMethod.", e); - throw new SLCommandException(4006); - } - String id = ctx.getIdValueFactory().createIdValue("Reference"); - - this.xmlObject = xmlObject; - this.reference = new XSECTReference(referenceURI, dm, transforms, null, id); - - } - - /** - * Sets the given xmlObject and creates and sets a corresponding - * Reference. - *

- * A transform to select the xmlObject's content is inserted at the top of to - * the optional transforms if given, or to a newly created - * Transforms element if transforms is - * null. - *

- * - * @param xmlObject - * the XMLObject - * @param transforms - * an optional Transforms element (may be - * null) - * - * @throws SLCommandException - * if creating the Reference fails - * @throws NullPointerException - * if xmlObject is null - */ - private void setXMLObjectAndReferenceXML(XMLObject xmlObject, XSECTTransforms transforms) throws SLCommandException { - - // create reference URI - String referenceURI = "#" + xmlObject.getId(); - - // create Transform to select ds:Object's children - Transform xpathTransform; - Transform c14nTransform; - try { - - XPathType xpath = new XPathType("id(\"" + xmlObject.getId() + "\")/node()", XPathType.Filter.INTERSECT); - List xpaths = Collections.singletonList(xpath); - XPathFilter2ParameterSpec params = new XPathFilter2ParameterSpec(xpaths); - - xpathTransform = ctx.getSignatureFactory().newTransform(Transform.XPATH2, params); - - // add exclusive canonicalization to avoid signing the namespace context of the ds:Object - c14nTransform = ctx.getSignatureFactory().newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null); - - } catch (NoSuchAlgorithmException e) { - // algorithm must be present - throw new SLRuntimeException(e); - } catch (InvalidAlgorithmParameterException e) { - // params must be appropriate - throw new SLRuntimeException(e); - } - - if (transforms == null) { - List newTransfroms = new ArrayList(); - newTransfroms.add(xpathTransform); - newTransfroms.add(c14nTransform); - transforms = new XSECTTransforms(newTransfroms); - } else { - transforms.insertTransform(xpathTransform); - } - - DigestMethod dm; - try { - dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); - } catch (NoSuchAlgorithmException e) { - log.error("Failed to get DigestMethod.", e); - throw new SLCommandException(4006); - } catch (InvalidAlgorithmParameterException e) { - log.error("Failed to get DigestMethod.", e); - throw new SLCommandException(4006); - } - String id = ctx.getIdValueFactory().createIdValue("Reference"); - - this.xmlObject = xmlObject; - this.reference = new XSECTReference(referenceURI, dm, transforms, null, id); - - } - - /** - * Parses the given xmlContent and returns a corresponding - * document fragment. - * - *

- * The to-be parsed content is surrounded by ... elements to - * allow for mixed (e.g. Text and Element) content in XMLContent. - *

- * - * @param xmlContent - * the XMLContent to-be parsed - * - * @return a document fragment containing the parsed nodes - * - * @throws SLCommandException - * if parsing the given xmlContent fails - * - * @throws NullPointerException - * if xmlContent is null - */ - private DocumentFragment parseDataObject(XMLContentType xmlContent) throws SLCommandException { - - ByteArrayOutputStream redirectedStream = xmlContent.getRedirectedStream(); - - // Note: We can assume a fixed character encoding of UTF-8 for the - // content of the redirect stream as the content has already been parsed - // and serialized again to the redirect stream. - - List inputStreams = new ArrayList(); - try { - // dummy start element - inputStreams.add(new ByteArrayInputStream("".getBytes("UTF-8"))); - - // content - inputStreams.add(new ByteArrayInputStream(redirectedStream.toByteArray())); - - // dummy end element - inputStreams.add(new ByteArrayInputStream("".getBytes("UTF-8"))); - } catch (UnsupportedEncodingException e) { - throw new SLRuntimeException(e); - } - - SequenceInputStream inputStream = new SequenceInputStream(Collections.enumeration(inputStreams)); - - // parse DataObject - Document doc = parseDataObject(inputStream, "UTF-8"); - - Element documentElement = doc.getDocumentElement(); - - if (documentElement == null || - !"dummy".equals(documentElement.getLocalName())) { - log.info("Failed to parse DataObject XMLContent."); - throw new SLCommandException(4111); - } - - DocumentFragment fragment = doc.createDocumentFragment(); - while (documentElement.getFirstChild() != null) { - fragment.appendChild(documentElement.getFirstChild()); - } - - // log parsed document - if (log.isTraceEnabled()) { - - StringWriter writer = new StringWriter(); - - writer.write("DataObject:\n"); - - LSOutput output = domImplLS.createLSOutput(); - output.setCharacterStream(writer); - output.setEncoding("UTF-8"); - LSSerializer serializer = domImplLS.createLSSerializer(); - serializer.getDomConfig().setParameter("xml-declaration", Boolean.FALSE); - serializer.write(fragment, output); - - log.trace(writer.toString()); - } - - return fragment; - - } - - /** - * Parses the given inputStream using the given - * encoding and returns the parsed document. - * - * @param inputStream - * the to-be parsed input - * - * @param encoding - * the encoding to be used for parsing the given - * inputStream - * - * @return the parsed document - * - * @throws SLCommandException - * if parsing the inputStream fails. - * - * @throws NullPointerException - * if inputStram is null - */ - private Document parseDataObject(InputStream inputStream, String encoding) throws SLCommandException { - - LSInput input = domImplLS.createLSInput(); - input.setByteStream(inputStream); - - if (encoding != null) { - input.setEncoding(encoding); - } - - LSParser parser = domImplLS.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null); - DOMConfiguration domConfig = parser.getDomConfig(); - SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); - domConfig.setParameter("error-handler", errorHandler); - domConfig.setParameter("validate", Boolean.FALSE); - - Document doc; - try { - doc = parser.parse(input); - } catch (DOMException e) { - log.info("Existing XML document cannot be parsed.", e); - throw new SLCommandException(4111); - } catch (LSException e) { - log.info("Existing XML document cannot be parsed. ", e); - throw new SLCommandException(4111); - } - - if (errorHandler.hasErrors()) { - // log errors - if (log.isInfoEnabled()) { - List errorMessages = errorHandler.getErrorMessages(); - StringBuffer sb = new StringBuffer(); - for (String errorMessage : errorMessages) { - sb.append(" "); - sb.append(errorMessage); - } - log.info("Existing XML document cannot be parsed. " + sb.toString()); - } - throw new SLCommandException(4111); - } - - return doc; - - } - - -} + + /** + * Configures this DataObject with the information provided within the given + * sl:DataObjectInfo. + * + * @param dataObjectInfo + * the sl:DataObjectInfo + * + * @throws SLCommandException + * if configuring this DataObject with the information provided in + * the sl:DataObjectInfo fails. + * @throws SLRequestException + * if the information provided in the sl:DataObjectInfo + * does not conform to the security layer specification. + * @throws NullPointerException + * if dataObjectInfo is null + */ + public void setDataObjectInfo(DataObjectInfoType dataObjectInfo) throws SLCommandException, SLRequestException { + + Base64XMLLocRefOptRefContentType dataObject = dataObjectInfo.getDataObject(); + String structure = dataObjectInfo.getStructure(); + + // select and unmarshal an appropriate transformation path if provided + // and set the final data meta information + XSECTTransforms transforms = createTransformsAndSetFinalDataMetaInfo(dataObjectInfo.getTransformsInfo()); + + if ("enveloping".equals(structure)) { + + // configure this DataObject as an enveloped DataObject + setEnvelopedDataObject(dataObject, transforms); + + } else if ("detached".equals(structure)) { + + // configure this DataObject as an detached DataObject + setDetachedDataObject(dataObject, transforms); + + } + // other values are not allowed by the schema and are therefore ignored + + } + + private byte[] getTransformsBytes(at.gv.egiz.slbinding.impl.TransformsInfoType ti) { + return ti.getRedirectedStream().toByteArray(); +// byte[] transformsBytes = ti.getRedirectedStream().toByteArray(); +// +// if (transformsBytes == null || transformsBytes.length == 0) { +// return null; +// } +// +// String dsigPrefix = ti.getNamespaceContext().getNamespaceURI("http://www.w3.org/2000/09/xmldsig#"); +// byte[] pre, post; +// if (dsigPrefix == null) { +// log.trace("XMLDSig not declared in outside dsig:Transforms"); +// pre = "".getBytes(); +// post = "".getBytes(); +// } else { +// log.trace("XMLDSig bound to prefix " + dsigPrefix); +// pre = ("").getBytes(); +// post = "".getBytes(); +// } +// +// byte[] workaround = new byte[pre.length + transformsBytes.length + post.length]; +// System.arraycopy(pre, 0, workaround, 0, pre.length); +// System.arraycopy(transformsBytes, 0, workaround, pre.length, transformsBytes.length); +// System.arraycopy(post, 0, workaround, pre.length + transformsBytes.length, post.length); +// return workaround; + } + + /** + * Configures this DataObject as an enveloped DataObject with the information + * provided within the given sl:DataObject. + * + * @param dataObject + * the sl:DataObject + * @param transforms + * an optional Transforms element (may be + * null) + * + * @throws SLCommandException + * if configuring this DataObject with the information provided in + * the sl:DataObject fails. + * @throws SLRequestException + * if the information provided in the sl:DataObject + * does not conform to the security layer specification. + * @throws NullPointerException + * if dataObject is null + */ + private void setEnvelopedDataObject( + Base64XMLLocRefOptRefContentType dataObject, XSECTTransforms transforms) + throws SLCommandException, SLRequestException { + + String reference = dataObject.getReference(); + if (reference == null) { + // + // case A + // + // The Reference attribute is not used; the content of sl:DataObject represents the data object. + // If the data object is XML-coded (the sl:XMLContent element is used in sl:DataObject), then it + // must be incorporated in the signature structure as parsed XML. + // + + if (dataObject.getBase64Content() != null) { + + log.debug("Adding DataObject (Base64Content) without a reference URI."); + + // create XMLObject + XMLObject xmlObject = createXMLObject(new ByteArrayInputStream(dataObject.getBase64Content())); + + setXMLObjectAndReferenceBase64(xmlObject, transforms); + + } else if (dataObject.getXMLContent() != null) { + + log.debug("Adding DataObject (XMLContent) without a reference URI."); + + // create XMLObject + DocumentFragment content = parseDataObject((XMLContentType) dataObject.getXMLContent()); + XMLObject xmlObject = createXMLObject(content); + + setXMLObjectAndReferenceXML(xmlObject, transforms); + + } else if (dataObject.getLocRefContent() != null) { + + log.debug("Adding DataObject (LocRefContent) without a reference URI."); + + setEnvelopedDataObject(dataObject.getLocRefContent(), transforms); + + } else { + + // not allowed + log.info("XML structure of the command request contains an " + + "invalid combination of optional elements or attributes. " + + "DataObject of structure='enveloped' without a reference must contain content."); + throw new SLRequestException(3003); + + } + + } else { + + if (dataObject.getBase64Content() == null && + dataObject.getXMLContent() == null && + dataObject.getLocRefContent() == null) { + + // + // case B + // + // The Reference attribute contains a URI that must be resolved by the + // Citizen Card Environment to obtain the data object. + // The content of sl:DataObject remains empty + // + + log.debug("Adding DataObject from reference URI '" + reference + "'."); + + setEnvelopedDataObject(reference, transforms); + + } else { + + // not allowed + log.info("XML structure of the command request contains an " + + "invalid combination of optional elements or attributes. " + + "DataObject of structure='enveloped' with reference must not contain content."); + throw new SLRequestException(3003); + + } + + + } + + } + + /** + * Configures this DataObject as an enveloped DataObject with the content to + * be dereferenced from the given reference. + * + * @param reference + * the reference URI + * @param transforms + * an optional Transforms element (may be + * null) + * + * @throws SLCommandException + * if dereferencing the given reference fails, or if + * configuring this DataObject with the data dereferenced from the + * given reference fails. + * @throws NullPointerException + * if reference is null + */ + private void setEnvelopedDataObject(String reference, XSECTTransforms transforms) throws SLCommandException { + + if (reference == null) { + throw new NullPointerException("Argument 'reference' must not be null."); + } + + // dereference URL + URLDereferencer dereferencer = URLDereferencer.getInstance(); + + StreamData streamData; + try { + streamData = dereferencer.dereference(reference, ctx.getDereferencerContext()); + } catch (IOException e) { + log.info("Failed to dereference XMLObject from '" + reference + "'.", e); + throw new SLCommandException(4110); + } + + Node childNode; + + String contentType = streamData.getContentType(); + if (contentType.startsWith("text/xml")) { + + // If content type is text/xml parse content. + String charset = HttpUtil.getCharset(contentType, true); + + Document doc = parseDataObject(streamData.getStream(), charset); + + childNode = doc.getDocumentElement(); + + if (childNode == null) { + log.info("Failed to parse XMLObject from '" + reference + "'."); + throw new SLCommandException(4111); + } + + XMLObject xmlObject = createXMLObject(childNode); + + setXMLObjectAndReferenceXML(xmlObject, transforms); + + } else { + + // Include content Base64 encoded. + XMLObject xmlObject = createXMLObject(streamData.getStream()); + + setXMLObjectAndReferenceBase64(xmlObject, transforms); + + } + + } + + /** + * Configures this DataObject as an detached DataObject with the information + * provided in the given sl:DataObject and optionally + * transforms. + * + * @param dataObject + * the sl:DataObject + * @param transforms + * an optional Transforms object, may be null + * + * @throws SLCommandException + * if configuring this DataObject with the information provided in + * the sl:DataObject fails. + * @throws SLRequestException + * if the information provided in the sl:DataObject + * does not conform to the security layer specification. + * @throws NullPointerException + * if dataObject is null + */ + private void setDetachedDataObject( + Base64XMLLocRefOptRefContentType dataObject, XSECTTransforms transforms) + throws SLCommandException, SLRequestException { + + String referenceURI = dataObject.getReference(); + + if (referenceURI == null) { + + // not allowed + log.info("XML structure of the command request contains an " + + "invalid combination of optional elements or attributes. " + + "DataObject of structure='detached' must contain a reference."); + throw new SLRequestException(3003); + + } else { + + DigestMethod dm; + try { + dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get DigestMethod.", e); + throw new SLCommandException(4006); + } catch (InvalidAlgorithmParameterException e) { + log.error("Failed to get DigestMethod.", e); + throw new SLCommandException(4006); + } + + String idValue = ctx.getIdValueFactory().createIdValue("Reference"); + + reference = new XSECTReference(referenceURI, dm, transforms, null, idValue); + + // case D: + // + // The Reference attribute contains a URI that is used by the Citizen Card + // Environment to code the reference to the data object as part of the XML + // signature (attribute URI in the dsig:Reference) element. The content of + // sl:DataObject represents the data object. + + if (dataObject.getLocRefContent() != null) { + String locRef = dataObject.getLocRefContent(); + try { + this.reference.setDereferencer(new LocRefDereferencer(ctx.getDereferencerContext(), locRef)); + } catch (URISyntaxException e) { + log.info("Invalid URI '" + locRef + "' in DataObject.", e); + throw new SLCommandException(4003); + } catch (IllegalArgumentException e) { + log.info("LocRef URI of '" + locRef + "' not supported in DataObject. ", e); + throw new SLCommandException(4003); + } + } else if (dataObject.getBase64Content() != null) { + byte[] base64Content = dataObject.getBase64Content(); + this.reference.setDereferencer(new ByteArrayDereferencer(base64Content)); + } else if (dataObject.getXMLContent() != null) { + XMLContentType xmlContent = (XMLContentType) dataObject.getXMLContent(); + byte[] bytes = xmlContent.getRedirectedStream().toByteArray(); + this.reference.setDereferencer(new ByteArrayDereferencer(bytes)); + } else { + + // case C: + // + // The Reference attribute contains a URI that must be resolved by the + // Citizen Card Environment to obtain the data object. The Reference + // attribute contains a URI that is used by the Citizen Card Environment + // to code the reference to the data object as part of the XML signature + // (attribute URI in the dsig:Reference) element. The content of + // sl:DataObject remains empty. + + } + + } + } + + /** + * Returns the preferred sl:TransformInfo from the given list of + * transformInfos, or null if none of the given + * transformInfos is preferred over the others. + * + * @param transformsInfos + * a list of sl:TransformInfos + * + * @return the selected sl:TransformInfo or null, if + * none is preferred over the others + */ + private TransformsInfoType selectPreferredTransformsInfo(List transformsInfos) { + + Map mimeTypes = new HashMap(); + + StringBuilder debugString = null; + if (log.isDebugEnabled()) { + debugString = new StringBuilder(); + debugString.append("Got " + transformsInfos.size() + " TransformsInfo(s):"); + } + + for (TransformsInfoType transformsInfoType : transformsInfos) { + MetaInfoType finalDataMetaInfo = transformsInfoType.getFinalDataMetaInfo(); + String mimeType = finalDataMetaInfo.getMimeType(); + String description = finalDataMetaInfo.getDescription(); + mimeTypes.put(mimeType, transformsInfoType); + if (debugString != null) { + debugString.append("\n FinalDataMetaInfo: MIME-Type="); + debugString.append(mimeType); + if (description != null) { + debugString.append(" "); + debugString.append(description); + } + } + } + + if (debugString != null) { + log.debug(debugString); + } + + // look for preferred transform + for (String mimeType : DEFAULT_PREFFERED_MIME_TYPES) { + if (mimeTypes.containsKey(mimeType)) { + return mimeTypes.get(mimeType); + } + } + + // no preferred transform + return null; + + } + + /** + * Create an instance of ds:Transforms from the given + * sl:TransformsInfo. + * + * @param transformsInfo + * the sl:TransformsInfo + * + * @return a corresponding unmarshalled ds:Transforms, or + * null if the given sl:TransformsInfo does + * not contain a dsig:Transforms element + * + * @throws SLRequestException + * if the ds:Transforms in the given + * transformsInfo are not valid or cannot be parsed. + * + * @throws MarshalException + * if the ds:Transforms in the given + * transformsInfo cannot be unmarshalled. + */ + private XSECTTransforms createTransforms(TransformsInfoType transformsInfo) throws SLRequestException, MarshalException { + + byte[] transforms = getTransformsBytes((at.gv.egiz.slbinding.impl.TransformsInfoType) transformsInfo); + + if (transforms != null && transforms.length > 0) { + // debug + if (log.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("Trying to parse transforms:\n"); + sb.append(new String(transforms, Charset.forName("UTF-8"))); + log.trace(sb); + } + + DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS(); + LSInput input = domImplLS.createLSInput(); + input.setByteStream(new ByteArrayInputStream(transforms)); + + LSParser parser = domImplLS.createLSParser( + DOMImplementationLS.MODE_SYNCHRONOUS, null); + DOMConfiguration domConfig = parser.getDomConfig(); + SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); + domConfig.setParameter("error-handler", errorHandler); + domConfig.setParameter("validate", Boolean.FALSE); + + Document document; + try { + document = parser.parse(input); + } catch (DOMException e) { + log.info("Failed to parse dsig:Transforms.", e); + throw new SLRequestException(3002); + } catch (LSException e) { + log.info("Failed to parse dsig:Transforms.", e); + throw new SLRequestException(3002); + } + + // adopt ds:Transforms + Element transformsElt = document.getDocumentElement(); + Node adoptedTransforms = ctx.getDocument().adoptNode(transformsElt); + + DOMCryptoContext context = new DOMCryptoContext(); + + // unmarshall ds:Transforms + return new XSECTTransforms(context, adoptedTransforms); + + } else { + return null; + } + + +// TransformsType transformsType = transformsInfo.getTransforms(); +// if (transformsType == null) { +// return null; +// } +// List transformList = transformsType.getTransform(); +// +// DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS(); +//// Document transformsDoc = ((DOMImplementation) domImplLS).createDocument("http://www.w3.org/2000/09/xmldsig#", "Transforms", null); +//// Element transforms = transformsDoc.getDocumentElement(); +// Document transformsDoc = DOMUtils.createDocument(); +// Element transforms = transformsDoc.createElementNS( +// "http://www.w3.org/2000/09/xmldsig#", +// Signature.XMLDSIG_PREFIX + ":Transforms"); +// transformsDoc.appendChild(transforms); +// +// for (TransformType transformType : transformList) { +// log.trace("found " + transformType.getClass().getName()); +// Element transform = transformsDoc.createElementNS( +// "http://www.w3.org/2000/09/xmldsig#", +// Signature.XMLDSIG_PREFIX + ":Transform"); +// String algorithm = transformType.getAlgorithm(); +// if (algorithm != null) { +// log.trace("found algorithm " + algorithm); +// transform.setAttribute("Algorithm", algorithm); +// } +// +// at.gv.egiz.slbinding.impl.TransformType t = (at.gv.egiz.slbinding.impl.TransformType) transformType; +// byte[] redirectedBytes = t.getRedirectedStream().toByteArray(); +// if (redirectedBytes != null && redirectedBytes.length > 0) { +// if (log.isTraceEnabled()) { +// StringBuilder sb = new StringBuilder(); +// sb.append("Trying to parse dsig:Transform:\n"); +// sb.append(new String(redirectedBytes, Charset.forName("UTF-8"))); +// log.trace(sb); +// } +// LSInput input = domImplLS.createLSInput(); +// input.setByteStream(new ByteArrayInputStream(redirectedBytes)); +// +// LSParser parser = domImplLS.createLSParser( +// DOMImplementationLS.MODE_SYNCHRONOUS, null); +// DOMConfiguration domConfig = parser.getDomConfig(); +// SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); +// domConfig.setParameter("error-handler", errorHandler); +// domConfig.setParameter("validate", Boolean.FALSE); +// +// try { +// Document redirectedDoc = parser.parse(input); +// Node redirected = transformsDoc.adoptNode(redirectedDoc.getDocumentElement()); +// transform.appendChild(redirected); +// +// //not supported by Xerces2.9.1 +//// Node redirected = parser.parseWithContext(input, transform, LSParser.ACTION_APPEND_AS_CHILDREN); +// +// } catch (DOMException e) { +// log.info("Failed to parse dsig:Transform.", e); +// throw new SLRequestException(3002); +// } catch (LSException e) { +// log.info("Failed to parse dsig:Transform.", e); +// throw new SLRequestException(3002); +// } +// } +// transforms.appendChild(transform); +// } +// +// //adopt ds:Transforms +// Node adoptedTransforms = ctx.getDocument().adoptNode(transforms); +// DOMCryptoContext context = new DOMCryptoContext(); +// +// // unmarshall ds:Transforms +// return new XSECTTransforms(context, adoptedTransforms); + + } + + /** + * Sets the mimeType and the description value + * for this DataObject. + * + * @param metaInfoType the sl:FinalMetaDataInfo + * + * @throws NullPointerException if metaInfoType is null + */ + private void setFinalDataMetaInfo(MetaInfoType metaInfoType) { + + this.mimeType = metaInfoType.getMimeType(); + this.description = metaInfoType.getDescription(); + + } + + /** + * Selects an appropriate transformation path (if present) from the given list + * of sl:TransformInfos, sets the corresponding final data meta info and + * returns the corresponding unmarshalled ds:Transforms. + * + * @param transformsInfos the sl:TransformInfos + * + * @return the unmarshalled ds:Transforms, or null if + * no transformation path has been selected. + * + * @throws SLRequestException if the given list ds:TransformsInfo contains + * an invalid ds:Transforms element, or no suitable transformation path + * can be found. + */ + private XSECTTransforms createTransformsAndSetFinalDataMetaInfo( + List transformsInfos) throws SLRequestException { + + TransformsInfoType preferredTransformsInfo = selectPreferredTransformsInfo(transformsInfos); + // try preferred transform + if (preferredTransformsInfo != null) { + + try { + XSECTTransforms transforms = createTransforms(preferredTransformsInfo); + setFinalDataMetaInfo(preferredTransformsInfo.getFinalDataMetaInfo()); + return transforms; + } catch (MarshalException e) { + + String mimeType = preferredTransformsInfo.getFinalDataMetaInfo().getMimeType(); + log.info("Failed to unmarshal preferred transformation path (MIME-Type=" + + mimeType + ").", e); + + } + + } + + // look for another suitable transformation path + for (TransformsInfoType transformsInfoType : transformsInfos) { + + try { + XSECTTransforms transforms = createTransforms(transformsInfoType); + setFinalDataMetaInfo(transformsInfoType.getFinalDataMetaInfo()); + return transforms; + } catch (MarshalException e) { + + String mimeType = transformsInfoType.getFinalDataMetaInfo().getMimeType(); + log.info("Failed to unmarshal transformation path (MIME-Type=" + + mimeType + ").", e); + } + + } + + // no suitable transformation path found + throw new SLRequestException(3003); + + } + + /** + * Create an XMLObject with the Base64 encoding of the given + * content. + * + * @param content + * the to-be Base64 encoded content + * @return an XMLObject with the Base64 encoded content + */ + private XMLObject createXMLObject(InputStream content) { + + Text textNode; + try { + textNode = at.gv.egiz.dom.DOMUtils.createBase64Text(content, ctx.getDocument()); + } catch (IOException e) { + log.error(e); + throw new SLRuntimeException(e); + } + + DOMStructure structure = new DOMStructure(textNode); + + String idValue = ctx.getIdValueFactory().createIdValue("Object"); + + return ctx.getSignatureFactory().newXMLObject(Collections.singletonList(structure), idValue, null, null); + + } + + /** + * Create an XMLObject with the given content node. + * + * @param content the content node + * + * @return an XMLObject with the given content + */ + private XMLObject createXMLObject(Node content) { + + String idValue = ctx.getIdValueFactory().createIdValue("Object"); + + List structures = Collections.singletonList(new DOMStructure(content)); + + return ctx.getSignatureFactory().newXMLObject(structures, idValue, null, null); + + } + + /** + * Sets the given xmlObject and creates and sets a corresponding + * Reference. + *

+ * A transform to Base64-decode the xmlObject's content is inserted at the top + * of to the optional transforms if given, or to a newly created + * Transforms element if transforms is + * null. + * + * @param xmlObject + * the XMLObject + * @param transforms + * an optional Transforms element (may be + * null) + * + * @throws SLCommandException + * if creating the Reference fails + * @throws NullPointerException + * if xmlObject is null + */ + private void setXMLObjectAndReferenceBase64(XMLObject xmlObject, XSECTTransforms transforms) throws SLCommandException { + + // create reference URI + // + // NOTE: the ds:Object can be referenced directly, as the Base64 transform + // operates on the text() of the input nodelist. + // + String referenceURI = "#" + xmlObject.getId(); + + // create Base64 Transform + Transform transform; + try { + transform = ctx.getSignatureFactory().newTransform(Transform.BASE64, (TransformParameterSpec) null); + } catch (NoSuchAlgorithmException e) { + // algorithm must be present + throw new SLRuntimeException(e); + } catch (InvalidAlgorithmParameterException e) { + // algorithm does not take parameters + throw new SLRuntimeException(e); + } + + if (transforms == null) { + transforms = new XSECTTransforms(Collections.singletonList(transform)); + } else { + transforms.insertTransform(transform); + } + + DigestMethod dm; + try { + dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get DigestMethod.", e); + throw new SLCommandException(4006); + } catch (InvalidAlgorithmParameterException e) { + log.error("Failed to get DigestMethod.", e); + throw new SLCommandException(4006); + } + String id = ctx.getIdValueFactory().createIdValue("Reference"); + + this.xmlObject = xmlObject; + this.reference = new XSECTReference(referenceURI, dm, transforms, null, id); + + } + + /** + * Sets the given xmlObject and creates and sets a corresponding + * Reference. + *

+ * A transform to select the xmlObject's content is inserted at the top of to + * the optional transforms if given, or to a newly created + * Transforms element if transforms is + * null. + *

+ * + * @param xmlObject + * the XMLObject + * @param transforms + * an optional Transforms element (may be + * null) + * + * @throws SLCommandException + * if creating the Reference fails + * @throws NullPointerException + * if xmlObject is null + */ + private void setXMLObjectAndReferenceXML(XMLObject xmlObject, XSECTTransforms transforms) throws SLCommandException { + + // create reference URI + String referenceURI = "#" + xmlObject.getId(); + + // create Transform to select ds:Object's children + Transform xpathTransform; + Transform c14nTransform; + try { + + XPathType xpath = new XPathType("id(\"" + xmlObject.getId() + "\")/node()", XPathType.Filter.INTERSECT); + List xpaths = Collections.singletonList(xpath); + XPathFilter2ParameterSpec params = new XPathFilter2ParameterSpec(xpaths); + + xpathTransform = ctx.getSignatureFactory().newTransform(Transform.XPATH2, params); + + // add exclusive canonicalization to avoid signing the namespace context of the ds:Object + c14nTransform = ctx.getSignatureFactory().newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null); + + } catch (NoSuchAlgorithmException e) { + // algorithm must be present + throw new SLRuntimeException(e); + } catch (InvalidAlgorithmParameterException e) { + // params must be appropriate + throw new SLRuntimeException(e); + } + + if (transforms == null) { + List newTransfroms = new ArrayList(); + newTransfroms.add(xpathTransform); + newTransfroms.add(c14nTransform); + transforms = new XSECTTransforms(newTransfroms); + } else { + transforms.insertTransform(xpathTransform); + } + + DigestMethod dm; + try { + dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get DigestMethod.", e); + throw new SLCommandException(4006); + } catch (InvalidAlgorithmParameterException e) { + log.error("Failed to get DigestMethod.", e); + throw new SLCommandException(4006); + } + String id = ctx.getIdValueFactory().createIdValue("Reference"); + + this.xmlObject = xmlObject; + this.reference = new XSECTReference(referenceURI, dm, transforms, null, id); + + } + + /** + * Parses the given xmlContent and returns a corresponding + * document fragment. + * + *

+ * The to-be parsed content is surrounded by ... elements to + * allow for mixed (e.g. Text and Element) content in XMLContent. + *

+ * + * @param xmlContent + * the XMLContent to-be parsed + * + * @return a document fragment containing the parsed nodes + * + * @throws SLCommandException + * if parsing the given xmlContent fails + * + * @throws NullPointerException + * if xmlContent is null + */ + private DocumentFragment parseDataObject(XMLContentType xmlContent) throws SLCommandException { + + ByteArrayOutputStream redirectedStream = xmlContent.getRedirectedStream(); + + // Note: We can assume a fixed character encoding of UTF-8 for the + // content of the redirect stream as the content has already been parsed + // and serialized again to the redirect stream. + + List inputStreams = new ArrayList(); + try { + // dummy start element + inputStreams.add(new ByteArrayInputStream("".getBytes("UTF-8"))); + + // content + inputStreams.add(new ByteArrayInputStream(redirectedStream.toByteArray())); + + // dummy end element + inputStreams.add(new ByteArrayInputStream("".getBytes("UTF-8"))); + } catch (UnsupportedEncodingException e) { + throw new SLRuntimeException(e); + } + + SequenceInputStream inputStream = new SequenceInputStream(Collections.enumeration(inputStreams)); + + // parse DataObject + Document doc = parseDataObject(inputStream, "UTF-8"); + + Element documentElement = doc.getDocumentElement(); + + if (documentElement == null || + !"dummy".equals(documentElement.getLocalName())) { + log.info("Failed to parse DataObject XMLContent."); + throw new SLCommandException(4111); + } + + DocumentFragment fragment = doc.createDocumentFragment(); + while (documentElement.getFirstChild() != null) { + fragment.appendChild(documentElement.getFirstChild()); + } + + // log parsed document + if (log.isTraceEnabled()) { + + StringWriter writer = new StringWriter(); + + writer.write("DataObject:\n"); + + LSOutput output = domImplLS.createLSOutput(); + output.setCharacterStream(writer); + output.setEncoding("UTF-8"); + LSSerializer serializer = domImplLS.createLSSerializer(); + serializer.getDomConfig().setParameter("xml-declaration", Boolean.FALSE); + serializer.write(fragment, output); + + log.trace(writer.toString()); + } + + return fragment; + + } + + /** + * Parses the given inputStream using the given + * encoding and returns the parsed document. + * + * @param inputStream + * the to-be parsed input + * + * @param encoding + * the encoding to be used for parsing the given + * inputStream + * + * @return the parsed document + * + * @throws SLCommandException + * if parsing the inputStream fails. + * + * @throws NullPointerException + * if inputStram is null + */ + private Document parseDataObject(InputStream inputStream, String encoding) throws SLCommandException { + + LSInput input = domImplLS.createLSInput(); + input.setByteStream(inputStream); + + if (encoding != null) { + input.setEncoding(encoding); + } + + LSParser parser = domImplLS.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null); + DOMConfiguration domConfig = parser.getDomConfig(); + SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); + domConfig.setParameter("error-handler", errorHandler); + domConfig.setParameter("validate", Boolean.FALSE); + + Document doc; + try { + doc = parser.parse(input); + } catch (DOMException e) { + log.info("Existing XML document cannot be parsed.", e); + throw new SLCommandException(4111); + } catch (LSException e) { + log.info("Existing XML document cannot be parsed. ", e); + throw new SLCommandException(4111); + } + + if (errorHandler.hasErrors()) { + // log errors + if (log.isInfoEnabled()) { + List errorMessages = errorHandler.getErrorMessages(); + StringBuffer sb = new StringBuffer(); + for (String errorMessage : errorMessages) { + sb.append(" "); + sb.append(errorMessage); + } + log.info("Existing XML document cannot be parsed. " + sb.toString()); + } + throw new SLCommandException(4111); + } + + return doc; + + } + + +} 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 8baa0137..9182e824 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 @@ -87,6 +87,8 @@ import at.gv.egiz.bku.utils.urldereferencer.StreamData; import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; import at.gv.egiz.dom.DOMUtils; +import at.gv.egiz.marshal.NamespacePrefix; +import at.gv.egiz.marshal.NamespacePrefixMapperImpl; import at.gv.egiz.slbinding.impl.XMLContentType; import at.gv.egiz.stal.STAL; import at.gv.egiz.xades.QualifyingPropertiesException; @@ -99,6 +101,7 @@ import at.gv.egiz.xades.QualifyingPropertiesFactory; * @author mcentner */ public class Signature { + public static final String XMLDSIG_PREFIX = "dsig"; /** * Logging facility. @@ -407,7 +410,7 @@ public class Signature { signContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE); - signContext.putNamespacePrefix(XMLSignature.XMLNS, "dsig"); + signContext.putNamespacePrefix(XMLSignature.XMLNS,XMLDSIG_PREFIX); signContext.setURIDereferencer(new URIDereferncerAdapter(ctx.getDereferencerContext())); diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java index 78172dcb..7ce7b42d 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java @@ -14,185 +14,186 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.bku.slcommands.impl.xsect; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import iaik.xml.crypto.XSecProvider; - -import java.io.IOException; -import java.io.InputStream; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.List; - +package at.gv.egiz.bku.slcommands.impl.xsect; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import iaik.xml.crypto.XSecProvider; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.List; + import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSocketFactory; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.crypto.MarshalException; -import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.crypto.dsig.DigestMethod; -import javax.xml.crypto.dsig.Reference; -import javax.xml.crypto.dsig.SignatureMethod; -import javax.xml.crypto.dsig.Transform; -import javax.xml.crypto.dsig.XMLObject; -import javax.xml.crypto.dsig.XMLSignatureException; -import javax.xml.crypto.dsig.XMLSignatureFactory; -import javax.xml.crypto.dsig.dom.DOMSignContext; -import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; -import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec; -import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.ls.DOMImplementationLS; -import org.w3c.dom.ls.LSOutput; -import org.w3c.dom.ls.LSSerializer; - -import at.buergerkarte.namespaces.securitylayer._1.CreateXMLSignatureRequestType; -import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; -import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; -import at.buergerkarte.namespaces.securitylayer._1.SignatureInfoCreationType; -import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.bku.slexceptions.SLRequestException; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.SignatureMethod; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.dom.DOMSignContext; +import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; +import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec; +import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSOutput; +import org.w3c.dom.ls.LSSerializer; + +import at.buergerkarte.namespaces.securitylayer._1.CreateXMLSignatureRequestType; +import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; +import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.buergerkarte.namespaces.securitylayer._1.SignatureInfoCreationType; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLViewerException; -import at.gv.egiz.bku.utils.urldereferencer.StreamData; -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; -import at.gv.egiz.bku.utils.urldereferencer.URLProtocolHandler; -import at.gv.egiz.dom.DOMUtils; -import at.gv.egiz.slbinding.RedirectEventFilter; -import at.gv.egiz.slbinding.RedirectUnmarshallerListener; - -public class SignatureTest { - - private class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory { - - @Override - public CanonicalizationMethod createCanonicalizationMethod( - SignatureContext signatureContext) { - - XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory(); - - try { - return signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public DigestMethod createDigestMethod(SignatureContext signatureContext) { - - XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory(); - - try { - return signatureFactory.newDigestMethod(DigestMethod.SHA1, (DigestMethodParameterSpec) null); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public SignatureMethod createSignatureMethod( - SignatureContext signatureContext) { - - XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory(); - - try { - return signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, (SignatureMethodParameterSpec) null); - } catch (Exception e) { - throw new RuntimeException(e); - } - - } - - } - - private static final String RESOURCE_PREFIX = "at/gv/egiz/bku/slcommands/impl/"; - - private static Unmarshaller unmarshaller; - - private static PrivateKey privateKey; - - private static X509Certificate certificate; - - @BeforeClass - public static void setUpClass() throws JAXBException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException { - - XSecProvider.addAsProvider(true); - - String packageName = ObjectFactory.class.getPackage().getName(); - packageName += ":" - + org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName(); - JAXBContext jaxbContext = JAXBContext.newInstance(packageName); - - unmarshaller = jaxbContext.createUnmarshaller(); - - initURLDereferencer(); - - ClassLoader classLoader = SignatureTest.class.getClassLoader(); - InputStream certStream = classLoader.getResourceAsStream(RESOURCE_PREFIX + "Cert.p12"); - assertNotNull("Certificate not found.", certStream); - - char[] passwd = "1622".toCharArray(); - - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(certStream, passwd); - String firstAlias = keystore.aliases().nextElement(); - certificate = (X509Certificate) keystore.getCertificate(firstAlias); - privateKey = (PrivateKey) keystore.getKey(firstAlias, passwd); - - } - - private static void initURLDereferencer() { - - URLDereferencer.getInstance().registerHandler("testlocal", new URLProtocolHandler() { - - @Override - public StreamData dereference(String url, URLDereferencerContext context) - throws IOException { - - ClassLoader classLoader = SignatureTest.class.getClassLoader(); - - String filename = url.split(":", 2)[1]; - - InputStream stream = classLoader.getResourceAsStream(RESOURCE_PREFIX + filename); - - if (stream == null) { - - throw new IOException("Failed to resolve resource '" + url + "'."); - - } else { - - String contentType; - if (filename.endsWith(".xml")) { - contentType = "text/xml"; - } else if (filename.endsWith(".txt")) { - contentType = "text/plain"; - } else { - contentType = ""; - } - - return new StreamData(url, contentType, stream); - - } - +import at.gv.egiz.bku.utils.urldereferencer.StreamData; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; +import at.gv.egiz.bku.utils.urldereferencer.URLProtocolHandler; +import at.gv.egiz.dom.DOMUtils; +import at.gv.egiz.slbinding.RedirectEventFilter; +import at.gv.egiz.slbinding.RedirectUnmarshallerListener; +import org.junit.Ignore; + +public class SignatureTest { + + private class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory { + + @Override + public CanonicalizationMethod createCanonicalizationMethod( + SignatureContext signatureContext) { + + XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory(); + + try { + return signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public DigestMethod createDigestMethod(SignatureContext signatureContext) { + + XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory(); + + try { + return signatureFactory.newDigestMethod(DigestMethod.SHA1, (DigestMethodParameterSpec) null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public SignatureMethod createSignatureMethod( + SignatureContext signatureContext) { + + XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory(); + + try { + return signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, (SignatureMethodParameterSpec) null); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + + } + + private static final String RESOURCE_PREFIX = "at/gv/egiz/bku/slcommands/impl/"; + + private static Unmarshaller unmarshaller; + + private static PrivateKey privateKey; + + private static X509Certificate certificate; + + @BeforeClass + public static void setUpClass() throws JAXBException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException { + + XSecProvider.addAsProvider(true); + + String packageName = ObjectFactory.class.getPackage().getName(); + packageName += ":" + + org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName(); + JAXBContext jaxbContext = JAXBContext.newInstance(packageName); + + unmarshaller = jaxbContext.createUnmarshaller(); + + initURLDereferencer(); + + ClassLoader classLoader = SignatureTest.class.getClassLoader(); + InputStream certStream = classLoader.getResourceAsStream(RESOURCE_PREFIX + "Cert.p12"); + assertNotNull("Certificate not found.", certStream); + + char[] passwd = "1622".toCharArray(); + + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(certStream, passwd); + String firstAlias = keystore.aliases().nextElement(); + certificate = (X509Certificate) keystore.getCertificate(firstAlias); + privateKey = (PrivateKey) keystore.getKey(firstAlias, passwd); + + } + + private static void initURLDereferencer() { + + URLDereferencer.getInstance().registerHandler("testlocal", new URLProtocolHandler() { + + @Override + public StreamData dereference(String url, URLDereferencerContext context) + throws IOException { + + ClassLoader classLoader = SignatureTest.class.getClassLoader(); + + String filename = url.split(":", 2)[1]; + + InputStream stream = classLoader.getResourceAsStream(RESOURCE_PREFIX + filename); + + if (stream == null) { + + throw new IOException("Failed to resolve resource '" + url + "'."); + + } else { + + String contentType; + if (filename.endsWith(".xml")) { + contentType = "text/xml"; + } else if (filename.endsWith(".txt")) { + contentType = "text/plain"; + } else { + contentType = ""; + } + + return new StreamData(url, contentType, stream); + + } + } @Override @@ -205,558 +206,600 @@ public class SignatureTest { public void setSSLSocketFactory(SSLSocketFactory socketFactory) { // TODO Auto-generated method stub - } - - }); - - } - - private Object unmarshal(String file) throws XMLStreamException, JAXBException { - - ClassLoader classLoader = SignatureTest.class.getClassLoader(); - InputStream resourceStream = classLoader.getResourceAsStream(RESOURCE_PREFIX + file); - assertNotNull(resourceStream); - - XMLInputFactory inputFactory = XMLInputFactory.newInstance(); - XMLEventReader eventReader = inputFactory.createXMLEventReader(resourceStream); - RedirectEventFilter redirectEventFilter = new RedirectEventFilter(); - XMLEventReader filteredReader = inputFactory.createFilteredReader(eventReader, redirectEventFilter); - - unmarshaller.setListener(new RedirectUnmarshallerListener(redirectEventFilter)); - - return unmarshaller.unmarshal(filteredReader); - - } - - // - // - // SignatureInfo - // - // - - @SuppressWarnings("unchecked") - private SignatureInfoCreationType unmarshalSignatureInfo(String file) throws JAXBException, XMLStreamException { - - Object object = unmarshal(file); - - Object requestType = ((JAXBElement) object).getValue(); - - assertTrue(requestType instanceof CreateXMLSignatureRequestType); - - SignatureInfoCreationType signatureInfo = ((CreateXMLSignatureRequestType) requestType).getSignatureInfo(); - - assertNotNull(signatureInfo); - - return signatureInfo; - - } - - @Test - public void testSetSignatureInfo_Base64_1() throws JAXBException, SLCommandException, XMLStreamException { - - SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_1.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), null); - - signature.setSignatureInfo(signatureInfo); - - Node parent = signature.getParent(); - Node nextSibling = signature.getNextSibling(); - - assertNotNull(parent); - assertTrue("urn:document".equals(parent.getNamespaceURI())); - assertTrue("XMLDocument".equals(parent.getLocalName())); - - assertNotNull(nextSibling); - assertTrue("urn:document".equals(nextSibling.getNamespaceURI())); - assertTrue("Paragraph".equals(nextSibling.getLocalName())); - - } - - @Test - public void testSetSignature_Base64_2() throws JAXBException, SLCommandException, XMLStreamException { - - SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_2.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), null); - - signature.setSignatureInfo(signatureInfo); - - Node parent = signature.getParent(); - Node nextSibling = signature.getNextSibling(); - - assertNotNull(parent); - assertTrue("XMLDocument".equals(parent.getLocalName())); - - assertNotNull(nextSibling); - assertTrue("Paragraph".equals(nextSibling.getLocalName())); - - } - - @Test - public void testSetSignature_Base64_3() throws JAXBException, SLCommandException, XMLStreamException { - - SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_3.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), null); - - signature.setSignatureInfo(signatureInfo); - - Node parent = signature.getParent(); - Node nextSibling = signature.getNextSibling(); - - assertNotNull(parent); - assertTrue("XMLDocument".equals(parent.getLocalName())); - - assertNotNull(nextSibling); - assertTrue("Paragraph".equals(nextSibling.getLocalName())); - - } - - @Test - public void testSetSignatureInfo_XMLContent_1() throws JAXBException, SLCommandException, XMLStreamException { - - SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_XMLContent_1.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), null); - - signature.setSignatureInfo(signatureInfo); - - Node parent = signature.getParent(); - Node nextSibling = signature.getNextSibling(); - - assertNotNull(parent); - assertTrue("urn:document".equals(parent.getNamespaceURI())); - assertTrue("Whole".equals(parent.getLocalName())); - - assertNull(nextSibling); - - } - - @Test - public void testSetSignature_Reference_1() throws JAXBException, SLCommandException, XMLStreamException { - - SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Reference_1.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), null); - - signature.setSignatureInfo(signatureInfo); - - Node parent = signature.getParent(); - Node nextSibling = signature.getNextSibling(); - - assertNotNull(parent); - assertTrue("urn:document".equals(parent.getNamespaceURI())); - assertTrue("Paragraph".equals(parent.getLocalName())); - - assertNull(nextSibling); - - } - - // - // - // DataObject - // - // - - @SuppressWarnings("unchecked") - private List unmarshalDataObjectInfo(String file) throws JAXBException, XMLStreamException { - - Object object = unmarshal(file); - - Object requestType = ((JAXBElement) object).getValue(); - - assertTrue(requestType instanceof CreateXMLSignatureRequestType); - - List dataObjectInfos = ((CreateXMLSignatureRequestType) requestType).getDataObjectInfo(); - - assertNotNull(dataObjectInfos); - - return dataObjectInfos; - - } - - private void signAndMarshalSignature(Signature signature) throws MarshalException, XMLSignatureException, SLCommandException, SLViewerException { - - Node parent = signature.getParent(); - Node nextSibling = signature.getNextSibling(); - - DOMSignContext signContext = (nextSibling == null) - ? new DOMSignContext(privateKey, parent) - : new DOMSignContext(privateKey, parent, nextSibling); - - signature.sign(signContext); - - Document document = signature.getDocument(); - - DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS(); - LSOutput output = domImplLS.createLSOutput(); - output.setByteStream(System.out); - - LSSerializer serializer = domImplLS.createLSSerializer(); -// serializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE); - serializer.getDomConfig().setParameter("namespaces", Boolean.FALSE); - serializer.write(document, output); - - } - - @SuppressWarnings("unchecked") - @Test - public void testDataObject_Base64Content_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { - - List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Base64Content_1.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); - - for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { - signature.addDataObject(dataObjectInfo); - } - - signature.setSignerCeritifcate(certificate); - - signature.buildXMLSignature(); - - signAndMarshalSignature(signature); - - List references = signature.getReferences(); - assertTrue(references.size() == 2); - - Reference reference = references.get(0); - assertNotNull(reference.getId()); - - List transforms = reference.getTransforms(); - assertTrue(transforms.size() == 1); - - Transform transform = transforms.get(0); - assertTrue(Transform.BASE64.equals(transform.getAlgorithm())); - - List objects = signature.getXMLObjects(); - assertNotNull(objects); - assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); - - XMLObject object = objects.get(0); - - assertTrue(("#" + object.getId()).equals(reference.getURI())); - - } - - @SuppressWarnings("unchecked") - @Test - public void testDataObject_XMLContent_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { - - List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_XMLContent_1.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); - - for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { - signature.addDataObject(dataObjectInfo); - } - - signature.setSignerCeritifcate(certificate); - - signature.buildXMLSignature(); - - signAndMarshalSignature(signature); - - List references = signature.getReferences(); - assertTrue(references.size() == 2); - - Reference reference = references.get(0); - assertNotNull(reference.getId()); - - List transforms = reference.getTransforms(); - assertTrue(transforms.size() == 2); - - Transform transform = transforms.get(0); - assertTrue(Transform.XPATH2.equals(transform.getAlgorithm())); - - List objects = signature.getXMLObjects(); - assertNotNull(objects); - assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); - - XMLObject object = objects.get(0); - - assertTrue(("#" + object.getId()).equals(reference.getURI())); - - } - - @SuppressWarnings("unchecked") - @Test - public void testDataObject_XMLContent_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { - - List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_XMLContent_2.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); - - for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { - signature.addDataObject(dataObjectInfo); - } - - signature.setSignerCeritifcate(certificate); - - signature.buildXMLSignature(); - - signAndMarshalSignature(signature); - - List references = signature.getReferences(); - assertTrue(references.size() == 2); - - Reference reference = references.get(0); - assertNotNull(reference.getId()); - - List transforms = reference.getTransforms(); - assertTrue(transforms.size() == 2); - - Transform transform = transforms.get(0); - assertTrue(Transform.XPATH2.equals(transform.getAlgorithm())); - - List objects = signature.getXMLObjects(); - assertNotNull(objects); - assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); - - XMLObject object = objects.get(0); - - assertTrue(("#" + object.getId()).equals(reference.getURI())); - - } - - - @SuppressWarnings("unchecked") - @Test - public void testDataObject_LocRefContent_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { - - List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_LocRefContent_1.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); - - for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { - signature.addDataObject(dataObjectInfo); - } - - signature.buildXMLSignature(); - - signAndMarshalSignature(signature); - - List references = signature.getReferences(); - assertTrue(references.size() == 2); - - Reference reference = references.get(0); - assertNotNull(reference.getId()); - - List transforms = reference.getTransforms(); - assertTrue(transforms.size() == 2); - - Transform transform = transforms.get(0); - assertTrue(Transform.XPATH2.equals(transform.getAlgorithm())); - - List objects = signature.getXMLObjects(); - assertNotNull(objects); - assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); - - XMLObject object = objects.get(0); - - assertTrue(("#" + object.getId()).equals(reference.getURI())); - - } - - @SuppressWarnings("unchecked") - @Test - public void testDataObject_LocRefContent_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { - - List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_LocRefContent_2.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); - - for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { - signature.addDataObject(dataObjectInfo); - } - - signature.buildXMLSignature(); - - signAndMarshalSignature(signature); - - List references = signature.getReferences(); - assertTrue(references.size() == 2); - - Reference reference = references.get(0); - assertNotNull(reference.getId()); - - List transforms = reference.getTransforms(); - assertTrue(transforms.size() == 1); - - Transform transform = transforms.get(0); - assertTrue(Transform.BASE64.equals(transform.getAlgorithm())); - - List objects = signature.getXMLObjects(); - assertNotNull(objects); - assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); - - XMLObject object = objects.get(0); - - assertTrue(("#" + object.getId()).equals(reference.getURI())); - - } - - @SuppressWarnings("unchecked") - @Test - public void testDataObject_Reference_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { - - List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Reference_1.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); - - for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { - signature.addDataObject(dataObjectInfo); - } - - signature.buildXMLSignature(); - - signAndMarshalSignature(signature); - - List references = signature.getReferences(); - assertTrue(references.size() == 2); - - Reference reference = references.get(0); - assertNotNull(reference.getId()); - - List transforms = reference.getTransforms(); - assertTrue(transforms.size() == 1); - - Transform transform = transforms.get(0); - assertTrue(Transform.BASE64.equals(transform.getAlgorithm())); - - List objects = signature.getXMLObjects(); - assertNotNull(objects); - assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); - - XMLObject object = objects.get(0); - - assertTrue(("#" + object.getId()).equals(reference.getURI())); - - } - - @SuppressWarnings("unchecked") - @Test - public void testDataObject_Detached_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { - - List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Detached_1.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); - - for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { - signature.addDataObject(dataObjectInfo); - } - - signature.buildXMLSignature(); - - signAndMarshalSignature(signature); - - List references = signature.getReferences(); - assertTrue(references.size() == 2); - - Reference reference = references.get(0); - assertNotNull(reference.getId()); - - List transforms = reference.getTransforms(); - assertTrue(transforms.size() == 0); - - List objects = signature.getXMLObjects(); - assertNotNull(objects); - assertTrue(objects.size() == 1); - - } - - @SuppressWarnings("unchecked") - @Test - public void testDataObject_Detached_Base64Content() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { - - List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Detached_Base64Content.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); - - for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { - signature.addDataObject(dataObjectInfo); - } - - signature.buildXMLSignature(); - - signAndMarshalSignature(signature); - - List references = signature.getReferences(); - assertTrue(references.size() == 2); - - Reference reference = references.get(0); - assertNotNull(reference.getId()); - - List transforms = reference.getTransforms(); - assertTrue(transforms.size() == 0); - - List objects = signature.getXMLObjects(); - assertNotNull(objects); - assertTrue(objects.size() == 1); - - } - - // - // - // TransformsInfo - // - // - - @SuppressWarnings("unchecked") - private CreateXMLSignatureRequestType unmarshalCreateXMLSignatureRequest(String file) throws JAXBException, XMLStreamException { - - Object object = unmarshal(file); - - Object requestType = ((JAXBElement) object).getValue(); - - assertTrue(requestType instanceof CreateXMLSignatureRequestType); - - return (CreateXMLSignatureRequestType) requestType; - - } - - - @SuppressWarnings("unchecked") - @Test - public void testTransformsInfo_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { - - CreateXMLSignatureRequestType requestType = unmarshalCreateXMLSignatureRequest("TransformsInfo_1.xml"); - - Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); - - - signature.setSignatureInfo(requestType.getSignatureInfo()); - - List dataObjectInfos = requestType.getDataObjectInfo(); - - for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { - signature.addDataObject(dataObjectInfo); - } - - signature.setSignerCeritifcate(certificate); - - signature.buildXMLSignature(); - - signAndMarshalSignature(signature); - - List references = signature.getReferences(); - assertTrue(references.size() == 2); - - Reference reference = references.get(0); - assertNotNull(reference.getId()); - - List transforms = reference.getTransforms(); - assertTrue("Size " + transforms.size() + "", transforms.size() == 3); - - Transform transform = transforms.get(0); - assertTrue(Transform.ENVELOPED.equals(transform.getAlgorithm())); - - List objects = signature.getXMLObjects(); - assertNotNull(objects); - assertTrue("Size " + objects.size() + " but should be 1.", objects.size() == 1); - - } - - -} + } + + }); + + } + + private Object unmarshal(String file) throws XMLStreamException, JAXBException { + + ClassLoader classLoader = SignatureTest.class.getClassLoader(); + InputStream resourceStream = classLoader.getResourceAsStream(RESOURCE_PREFIX + file); + assertNotNull(resourceStream); + + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + XMLEventReader eventReader = inputFactory.createXMLEventReader(resourceStream); + RedirectEventFilter redirectEventFilter = new RedirectEventFilter(); + XMLEventReader filteredReader = inputFactory.createFilteredReader(eventReader, redirectEventFilter); + + unmarshaller.setListener(new RedirectUnmarshallerListener(redirectEventFilter)); + + return unmarshaller.unmarshal(filteredReader); + + } + + // + // + // SignatureInfo + // + // + + @SuppressWarnings("unchecked") + private SignatureInfoCreationType unmarshalSignatureInfo(String file) throws JAXBException, XMLStreamException { + + Object object = unmarshal(file); + + Object requestType = ((JAXBElement) object).getValue(); + + assertTrue(requestType instanceof CreateXMLSignatureRequestType); + + SignatureInfoCreationType signatureInfo = ((CreateXMLSignatureRequestType) requestType).getSignatureInfo(); + + assertNotNull(signatureInfo); + + return signatureInfo; + + } + + @Test + public void testSetSignatureInfo_Base64_1() throws JAXBException, SLCommandException, XMLStreamException { + + SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_1.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), null); + + signature.setSignatureInfo(signatureInfo); + + Node parent = signature.getParent(); + Node nextSibling = signature.getNextSibling(); + + assertNotNull(parent); + assertTrue("urn:document".equals(parent.getNamespaceURI())); + assertTrue("XMLDocument".equals(parent.getLocalName())); + + assertNotNull(nextSibling); + assertTrue("urn:document".equals(nextSibling.getNamespaceURI())); + assertTrue("Paragraph".equals(nextSibling.getLocalName())); + + } + + @Test + public void testSetSignature_Base64_2() throws JAXBException, SLCommandException, XMLStreamException { + + SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_2.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), null); + + signature.setSignatureInfo(signatureInfo); + + Node parent = signature.getParent(); + Node nextSibling = signature.getNextSibling(); + + assertNotNull(parent); + assertTrue("XMLDocument".equals(parent.getLocalName())); + + assertNotNull(nextSibling); + assertTrue("Paragraph".equals(nextSibling.getLocalName())); + + } + + @Test + public void testSetSignature_Base64_3() throws JAXBException, SLCommandException, XMLStreamException { + + SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_3.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), null); + + signature.setSignatureInfo(signatureInfo); + + Node parent = signature.getParent(); + Node nextSibling = signature.getNextSibling(); + + assertNotNull(parent); + assertTrue("XMLDocument".equals(parent.getLocalName())); + + assertNotNull(nextSibling); + assertTrue("Paragraph".equals(nextSibling.getLocalName())); + + } + + @Test + public void testSetSignatureInfo_XMLContent_1() throws JAXBException, SLCommandException, XMLStreamException { + + SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_XMLContent_1.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), null); + + signature.setSignatureInfo(signatureInfo); + + Node parent = signature.getParent(); + Node nextSibling = signature.getNextSibling(); + + assertNotNull(parent); + assertTrue("urn:document".equals(parent.getNamespaceURI())); + assertTrue("Whole".equals(parent.getLocalName())); + + assertNull(nextSibling); + + } + + @Test + public void testSetSignature_Reference_1() throws JAXBException, SLCommandException, XMLStreamException { + + SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Reference_1.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), null); + + signature.setSignatureInfo(signatureInfo); + + Node parent = signature.getParent(); + Node nextSibling = signature.getNextSibling(); + + assertNotNull(parent); + assertTrue("urn:document".equals(parent.getNamespaceURI())); + assertTrue("Paragraph".equals(parent.getLocalName())); + + assertNull(nextSibling); + + } + + // + // + // DataObject + // + // + + @SuppressWarnings("unchecked") + private List unmarshalDataObjectInfo(String file) throws JAXBException, XMLStreamException { + + Object object = unmarshal(file); + + Object requestType = ((JAXBElement) object).getValue(); + + assertTrue(requestType instanceof CreateXMLSignatureRequestType); + + List dataObjectInfos = ((CreateXMLSignatureRequestType) requestType).getDataObjectInfo(); + + assertNotNull(dataObjectInfos); + + return dataObjectInfos; + + } + + private void signAndMarshalSignature(Signature signature) throws MarshalException, XMLSignatureException, SLCommandException, SLViewerException { + + Node parent = signature.getParent(); + Node nextSibling = signature.getNextSibling(); + + DOMSignContext signContext = (nextSibling == null) + ? new DOMSignContext(privateKey, parent) + : new DOMSignContext(privateKey, parent, nextSibling); + + signature.sign(signContext); + + Document document = signature.getDocument(); + + DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS(); + LSOutput output = domImplLS.createLSOutput(); + output.setByteStream(System.out); + + LSSerializer serializer = domImplLS.createLSSerializer(); +// serializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE); + serializer.getDomConfig().setParameter("namespaces", Boolean.FALSE); + serializer.write(document, output); + + } + + @SuppressWarnings("unchecked") + @Test + public void testDataObject_Base64Content_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Base64Content_1.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.setSignerCeritifcate(certificate); + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue(transforms.size() == 1); + + Transform transform = transforms.get(0); + assertTrue(Transform.BASE64.equals(transform.getAlgorithm())); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); + + XMLObject object = objects.get(0); + + assertTrue(("#" + object.getId()).equals(reference.getURI())); + + } + + @SuppressWarnings("unchecked") + @Test + public void testDataObject_XMLContent_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_XMLContent_1.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.setSignerCeritifcate(certificate); + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue(transforms.size() == 2); + + Transform transform = transforms.get(0); + assertTrue(Transform.XPATH2.equals(transform.getAlgorithm())); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); + + XMLObject object = objects.get(0); + + assertTrue(("#" + object.getId()).equals(reference.getURI())); + + } + + @SuppressWarnings("unchecked") + @Test + public void testDataObject_XMLContent_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_XMLContent_2.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.setSignerCeritifcate(certificate); + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue(transforms.size() == 2); + + Transform transform = transforms.get(0); + assertTrue(Transform.XPATH2.equals(transform.getAlgorithm())); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); + + XMLObject object = objects.get(0); + + assertTrue(("#" + object.getId()).equals(reference.getURI())); + + } + + + @SuppressWarnings("unchecked") + @Test + public void testDataObject_LocRefContent_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_LocRefContent_1.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue(transforms.size() == 2); + + Transform transform = transforms.get(0); + assertTrue(Transform.XPATH2.equals(transform.getAlgorithm())); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); + + XMLObject object = objects.get(0); + + assertTrue(("#" + object.getId()).equals(reference.getURI())); + + } + + @SuppressWarnings("unchecked") + @Test + public void testDataObject_LocRefContent_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_LocRefContent_2.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue(transforms.size() == 1); + + Transform transform = transforms.get(0); + assertTrue(Transform.BASE64.equals(transform.getAlgorithm())); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); + + XMLObject object = objects.get(0); + + assertTrue(("#" + object.getId()).equals(reference.getURI())); + + } + + @SuppressWarnings("unchecked") + @Test + public void testDataObject_Reference_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Reference_1.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue(transforms.size() == 1); + + Transform transform = transforms.get(0); + assertTrue(Transform.BASE64.equals(transform.getAlgorithm())); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); + + XMLObject object = objects.get(0); + + assertTrue(("#" + object.getId()).equals(reference.getURI())); + + } + + @SuppressWarnings("unchecked") + @Test + public void testDataObject_Detached_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Detached_1.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue(transforms.size() == 0); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue(objects.size() == 1); + + } + + @SuppressWarnings("unchecked") + @Test + public void testDataObject_Detached_Base64Content() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + List dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Detached_Base64Content.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue(transforms.size() == 0); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue(objects.size() == 1); + + } + + // + // + // TransformsInfo + // + // + + @SuppressWarnings("unchecked") + private CreateXMLSignatureRequestType unmarshalCreateXMLSignatureRequest(String file) throws JAXBException, XMLStreamException { + + Object object = unmarshal(file); + + Object requestType = ((JAXBElement) object).getValue(); + + assertTrue(requestType instanceof CreateXMLSignatureRequestType); + + return (CreateXMLSignatureRequestType) requestType; + + } + + + @SuppressWarnings("unchecked") + @Test + public void testTransformsInfo_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + CreateXMLSignatureRequestType requestType = unmarshalCreateXMLSignatureRequest("TransformsInfo_1.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + + signature.setSignatureInfo(requestType.getSignatureInfo()); + + List dataObjectInfos = requestType.getDataObjectInfo(); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.setSignerCeritifcate(certificate); + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue("Size " + transforms.size() + "", transforms.size() == 3); + + Transform transform = transforms.get(0); + assertTrue(Transform.ENVELOPED.equals(transform.getAlgorithm())); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue("Size " + objects.size() + " but should be 1.", objects.size() == 1); + + } + + @SuppressWarnings("unchecked") + @Test + @Ignore + public void testTransformsInfo_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + + CreateXMLSignatureRequestType requestType = unmarshalCreateXMLSignatureRequest("TransformsInfo_2.xml"); + + Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + + signature.setSignatureInfo(requestType.getSignatureInfo()); + + List dataObjectInfos = requestType.getDataObjectInfo(); + + for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { + signature.addDataObject(dataObjectInfo); + } + + signature.setSignerCeritifcate(certificate); + + signature.buildXMLSignature(); + + signAndMarshalSignature(signature); + + List references = signature.getReferences(); + assertTrue(references.size() == 2); + + Reference reference = references.get(0); + assertNotNull(reference.getId()); + + List transforms = reference.getTransforms(); + assertTrue("Size " + transforms.size() + "", transforms.size() == 2); + + Transform transform = transforms.get(0); + assertTrue(Transform.XSLT.equals(transform.getAlgorithm())); + + List objects = signature.getXMLObjects(); + assertNotNull(objects); + assertTrue("Size " + objects.size() + " but should be 1.", objects.size() == 1); + + } + + +} diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/impl/TransformsInfo_2.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/impl/TransformsInfo_2.xml new file mode 100644 index 00000000..f43dc61a --- /dev/null +++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/impl/TransformsInfo_2.xml @@ -0,0 +1,397 @@ + + + SecureSignatureKeypair + + + + + + + + + + + Signatur der Anmeldedaten + + + +

Signatur der Anmeldedaten

+

+

Mit meiner elektronischen Signatur beantrage ich, + + , geboren am . . , in der Rolle als (OID***= ), den Zugang zur gesicherten Anwendung.

+

+

Datum und Uhrzeit: . . , : + : +

+ +

HPI(**):

+
+ +

wbPK(*):

+
+ +
+

Ich bin weiters ermächtigt als von + , geboren am . . + + , + , in deren Auftrag zu handeln. +

wbPK(*) des Vollmachtgebers:

+
+

+

+ + + +

+


+ + +

+


+
+ +

+


+
+ + +
(*) wbPK: Das wirtschaftsbereichsspezifische + Personenkennzeichen wird aus den jeweiligen + Stammzahlen des Bürgers und des Wirtschaftsunternehmens + berechnet und ermöglicht eine eindeutige Zuordnung des + Bürgers zum Wirtschaftsunternehmen.
+
+ +
(**) HPI: Der eHealth Professional + Identifier wird aus den jeweiligen Stammzahlen + der Gesundheitsdiensteanbieterinnen / + Gesundheitsdiensteanbieter berechnet und ermöglicht eine + eindeutige Zuordnung der Gesundheitsdiensteanbieterin / + des Gesundheitsdiensteanbieters im + Gesundheitsbereich.
+
+ +
(***) OID: Object Identifier sind + standardisierte Objekt-Bezeichner und beschreiben + eindeutig die Rollen des GDA-Token Inhabers.
+
+ + +
+
+
+ +
+ + application/xhtml+xml + +
+ + + + + + + + + + Signatur der Anmeldedaten + + +

Signatur der Anmeldedaten

+

+

Mit meiner elektronischen Signatur beantrage ich, + + , geboren am . . , in der Rolle als (OID***= ), den Zugang zur gesicherten Anwendung.

+

+

Datum und Uhrzeit: . . , : + : +

+ +

HPI(**):

+
+ +

wbPK(*):

+
+ +
+

Ich bin weiters ermächtigt als von + , geboren am . . + + , + , in deren Auftrag zu handeln. +

wbPK(*) des Vollmachtgebers:

+
+

+

+ + + +

+


+ + +

+


+
+ +

+


+
+ + +
(*) wbPK: Das wirtschaftsbereichsspezifische + Personenkennzeichen wird aus den jeweiligen + Stammzahlen des Bürgers und des Wirtschaftsunternehmens + berechnet und ermöglicht eine eindeutige Zuordnung des + Bürgers zum Wirtschaftsunternehmen.
+
+ +
(**) HPI: Der eHealth Professional Identifier + wird aus den jeweiligen Stammzahlen der + Gesundheitsdiensteanbieterinnen / + Gesundheitsdiensteanbieter berechnet und ermöglicht eine + eindeutige Zuordnung der Gesundheitsdiensteanbieterin / + des Gesundheitsdiensteanbieters im + Gesundheitsbereich.
+
+ +
(***) OID: Object Identifier sind standardisierte + Objekt-Bezeichner und beschreiben eindeutig die Rollen + des GDA-Token Inhabers.
+
+ + +
+
+
+ +
+ + text/html + +
+ + + + + + + + Mit meiner elektronischen Signatur beantrage ich, + + , geboren am + + . + + . + + , + + in der Rolle als + + (OID***= + ) + , + + den Zugang zur gesicherten Anwendung. + Datum und Uhrzeit: + + . + + . + + , + + : + + : + + + + HPI(**): + + + + + wbPK(*): + + + + + Ich bin weiters ermächtigt als + + von + + + , geboren am + + . + + . + + + + , + + + , in deren Auftrag zu handeln. + + + wbPK(*) des Vollmachtgebers: + + + + + + (*) wbPK: Das wirtschaftsbereichsspezifische Personenkennzeichen wird aus den jeweiligen Stammzahlen des Bürgers und des Wirtschaftsunternehmens berechnet und ermöglicht eine eindeutige Zuordnung des Bürgers zum Wirtschaftsunternehmen. + + + (**) HPI: Der eHealth Professional Identifier wird aus den jeweiligen Stammzahlen der Gesundheitsdiensteanbieterinnen / Gesundheitsdiensteanbieter berechnet und ermöglicht eine eindeutige Zuordnung der Gesundheitsdiensteanbieterin / des Gesundheitsdiensteanbieters im Gesundheitsbereich. + + + (***) OID: Object Identifier sind standardisierte Objekt-Bezeichner und beschreiben eindeutig die Rollen des GDA-Token Inhabers. + + + + + + + not(text()) + + + + text/plain + + +
+ + + + + + + https://demo.egiz.gv.at/exchange-moa-id-auth/ + + + + + LTpz8VYzns2jrx0J8Gm/R/nAhxA= + urn:publicid:gv.at:wbpk+FN+TODO + + + + + https://apps.egiz.gv.at/urlaubsschein-frontend/moaid-login + + + 1971-11-10 + + + + + + /saml:Assertion + +
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 13c57686..86223854 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -30,8 +30,6 @@ package at.gv.egiz.smcc; import java.nio.charset.Charset; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -41,7 +39,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ACOSCard extends AbstractSignatureCard implements SignatureCard { - + private static Log log = LogFactory.getLog(ACOSCard.class); public static final byte[] AID_DEC = new byte[] { (byte) 0xA0, (byte) 0x00, @@ -100,8 +98,15 @@ 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; + public ACOSCard() { super("at/gv/egiz/smcc/ACOSCard"); + pinSpecs.add(PINSPEC_INF, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name"), KID_PIN_INF, null)); + pinSpecs.add(PINSPEC_DEC, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name"), KID_PIN_DEC, null)); + pinSpecs.add(PINSPEC_SIG, new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SIG, null)); } /* (non-Javadoc) @@ -165,7 +170,8 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { try { if ("IdentityLink".equals(infobox)) { - PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name")); + PINSpec spec = pinSpecs.get(PINSPEC_INF); + //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name")); int retries = -1; String pin = null; @@ -219,7 +225,8 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { - PINSpec spec = new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); + PINSpec spec = pinSpecs.get(PINSPEC_SIG); + //new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); int retries = -1; String pin = null; @@ -260,7 +267,8 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { - PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name")); + PINSpec spec = pinSpecs.get(PINSPEC_DEC); + //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name")); int retries = -1; String pin = null; @@ -321,11 +329,6 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard { 0x00, fid, 256)); } - @Override - public byte[] getKIDs() { - return new byte[] { KID_PIN_DEC, KID_PIN_INF, KID_PIN_SIG }; - } - @Override public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { 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 67f090a5..cb068725 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -31,7 +31,11 @@ package at.gv.egiz.smcc; 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 javax.smartcardio.ATR; @@ -49,6 +53,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { private static Log log = LogFactory.getLog(AbstractSignatureCard.class); + protected List pinSpecs = new ArrayList(); + private ResourceBundle i18n; private String resourceBundleName; @@ -433,4 +439,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { } } + @Override + public List getPINSpecs() { + return pinSpecs; + } } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java b/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java index 0852d664..d180ddf0 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java @@ -35,23 +35,40 @@ public class PINSpec { String name_; + byte kid_; + + byte[] context_aid_; + + /** + * + * @param minLenght + * @param maxLength + * @param rexepPattern + * @param resourceBundle + * @param name + * @param kid the keyId for this pin + */ public PINSpec(int minLenght, int maxLength, String rexepPattern, - ResourceBundle resourceBundle, String name) { + ResourceBundle resourceBundle, String name, byte kid, byte[] contextAID) { minLength_ = minLenght; maxLength_ = maxLength; rexepPattern_ = rexepPattern; resourceBundle_ = resourceBundle; name_ = name; + kid_ = kid; + context_aid_ = contextAID; } public PINSpec(int minLenght, int maxLength, String rexepPattern, - String name) { + String name, byte kid, byte[] contextAID) { minLength_ = minLenght; maxLength_ = maxLength; rexepPattern_ = rexepPattern; name_ = name; + kid_ = kid; + context_aid_ = contextAID; } @@ -75,7 +92,14 @@ public class PINSpec { public String getRexepPattern() { return rexepPattern_; } - + + public byte getKID() { + return kid_; + } + + public byte[] getContextAID() { + return context_aid_; + } } 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 e80c6683..ae43629e 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -29,10 +29,8 @@ package at.gv.egiz.smcc; import java.math.BigInteger; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; @@ -42,7 +40,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class STARCOSCard extends AbstractSignatureCard implements SignatureCard { - + /** * Logging facility. */ @@ -155,12 +153,17 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard }; public static final byte KID_PIN_CARD = (byte) 0x01; - + + private static final int PINSPEC_CARD = 0; + private static final int PINSPEC_SS = 1; + /** * Creates an new instance. */ public STARCOSCard() { super("at/gv/egiz/smcc/STARCOSCard"); + pinSpecs.add(PINSPEC_CARD, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name"), KID_PIN_CARD, null)); + pinSpecs.add(PINSPEC_SS, new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SS, AID_DF_SS)); } @Override @@ -210,7 +213,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard try { if ("IdentityLink".equals(infobox)) { - PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); + PINSpec spec = pinSpecs.get(PINSPEC_CARD); + //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); int retries = -1; String pin = null; @@ -302,7 +306,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { - PINSpec spec = new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); + PINSpec spec = pinSpecs.get(PINSPEC_SS); + //new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); int retries = -1; String pin = null; @@ -334,7 +339,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { - PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); + PINSpec spec = pinSpecs.get(PINSPEC_CARD); + //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); int retries = -1; String pin = null; @@ -455,11 +461,6 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard } } - @Override - public byte[] getKIDs() { - return new byte[] { KID_PIN_CARD, KID_PIN_SS }; - } - /** * VERIFY PIN *

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 bad7ccf6..8dc4ac2a 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -36,9 +36,13 @@ import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; +import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; import java.util.Locale; +import java.util.Map; import javax.smartcardio.Card; import javax.smartcardio.CardTerminal; @@ -311,7 +315,7 @@ public class SWCard implements SignatureCard { if (password == null) { - PINSpec pinSpec = new PINSpec(0, -1, ".", "KeyStore-Password"); + PINSpec pinSpec = new PINSpec(0, -1, ".", "KeyStore-Password", (byte) 0x01, null); password = provider.providePIN(pinSpec, -1); @@ -390,13 +394,13 @@ public class SWCard implements SignatureCard { } @Override - public byte[] getKIDs() { - return null; + public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { + return -1; } @Override - public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { - return -1; + public List getPINSpecs() { + return new ArrayList(); } } 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 1ec35b78..1e5e09c8 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.List; import java.util.Locale; +import java.util.Map; import javax.smartcardio.Card; import javax.smartcardio.CardTerminal; @@ -118,10 +119,10 @@ public interface SignatureCard { PINProvider provider) throws SignatureCardException, InterruptedException; /** - * get the KIDs for the availabel PINs + * Get the KIDs for all available PINs and the corresponding PINSpecs * @return array of KIDs */ - public byte[] getKIDs(); + public List getPINSpecs(); /** * 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 e10ba8f9..b6c5a8ca 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 @@ -102,6 +102,9 @@ public abstract class AbstractBKUWorker extends AbstractSMCCSTAL implements Acti @Override protected boolean waitForCard() { + if (signatureCard != null) { + return false; + } SMCCHelper smccHelper = new SMCCHelper(); actionCommandList.clear(); actionCommandList.add("cancel"); 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 a5f8a771..a5d6df23 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -86,15 +86,16 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements } - @Override - public byte[] getKIDs() { - return null; - } @Override public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { return 0; } + + @Override + public List getPINSpecs() { + return new ArrayList(); + } }; return false; diff --git a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java new file mode 100644 index 00000000..c03f17cd --- /dev/null +++ b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.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.marshal; + +/** + * + * @author Clemens Orthacker + */ +public interface NamespacePrefix { + String CARDCHANNEL_PREFIX = "cc"; + String ECDSA_PREFIX = "ecdsa"; + String PERSONDATA_PREFIX = "pr"; + String SAML10_PREFIX = "saml"; + String SL_PREFIX = "sl"; + String XADES_PREFIX = "xades"; + String XMLDSIG_PREFIX = "xmldsig"; + String XSI_PREFIX = "xsi"; + +} diff --git a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java index a08c1188..519f6b1f 100644 --- a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java +++ b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java @@ -36,35 +36,35 @@ public class NamespacePrefixMapperImpl extends NamespacePrefixMapper { log.trace("prefix for namespace " + namespaceUri + " requested"); } if ("http://www.w3.org/2001/XMLSchema-instance".equals(namespaceUri)) { - return "xsi"; + return NamespacePrefix.XSI_PREFIX; } if ("http://www.w3.org/2000/09/xmldsig#".equals(namespaceUri)) { - return "dsig"; + return NamespacePrefix.XMLDSIG_PREFIX; } if ("http://www.buergerkarte.at/namespaces/securitylayer/1.2#".equals(namespaceUri)) { - return "sl"; + return NamespacePrefix.SL_PREFIX; } if ("http://www.buergerkarte.at/cardchannel".equals(namespaceUri)) { - return "cc"; + return NamespacePrefix.CARDCHANNEL_PREFIX; } if ("http://www.w3.org/2001/04/xmldsig-more#".equals(namespaceUri)) { - return "ecdsa"; + return NamespacePrefix.ECDSA_PREFIX; } if ("http://reference.e-government.gv.at/namespace/persondata/20020228#".equals(namespaceUri)) { - return "pr"; + return NamespacePrefix.PERSONDATA_PREFIX; } if ("urn:oasis:names:tc:SAML:1.0:assertion".equals(namespaceUri)) { - return "saml"; + return NamespacePrefix.SAML10_PREFIX; } if ("http://uri.etsi.org/01903/v1.1.1#".equals(namespaceUri)) { - return "xades"; + return NamespacePrefix.XADES_PREFIX; } return suggestion; diff --git a/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java b/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java index d2a7fb30..14c5ba48 100644 --- a/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java +++ b/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.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. @@ -33,79 +33,84 @@ import javax.xml.stream.events.XMLEvent; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +/* + * TODO: don't set redirect stream from caller (caller does not know whether redirection will be triggered) + * rather create on trigger and pass to caller + */ public class RedirectEventFilter implements EventFilter { - public static final String DEFAULT_ENCODING = "UTF-8"; - private static Log log = LogFactory.getLog(RedirectEventFilter.class); - protected XMLEventWriter redirectWriter = null; - protected Set redirectTriggers = null; - private int depth = -1; - protected NamespaceContext currentNamespaceContext = null; + public static final String DEFAULT_ENCODING = "UTF-8"; + private static Log log = LogFactory.getLog(RedirectEventFilter.class); + protected XMLEventWriter redirectWriter = null; + protected Set redirectTriggers = null; + private int depth = -1; + protected NamespaceContext currentNamespaceContext = null; - /** - * Event redirection is disabled, set a redirect stream to enable. - */ - public RedirectEventFilter() { - redirectWriter = null; - // redirectTriggers = null; - } + /** + * Event redirection is disabled, set a redirect stream to enable. + */ + public RedirectEventFilter() { + redirectWriter = null; + // redirectTriggers = null; + } - /** - * - * @param redirectStream - * if null, no events are redirected - * @param redirectTriggers - * if null, all events are redirected - */ - public RedirectEventFilter(OutputStream redirectStream, String encoding) - throws XMLStreamException { // , List redirectTriggers - if (redirectStream != null) { - XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); - if (encoding == null) { - encoding = DEFAULT_ENCODING; - } - this.redirectWriter = outputFactory.createXMLEventWriter(redirectStream, + /** + * + * @param redirectStream + * if null, no events are redirected + * @param redirectTriggers + * if null, all events are redirected + */ + public RedirectEventFilter(OutputStream redirectStream, String encoding) + throws XMLStreamException { // , List redirectTriggers + if (redirectStream != null) { + XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); + if (encoding == null) { + encoding = DEFAULT_ENCODING; + } + this.redirectWriter = outputFactory.createXMLEventWriter(redirectStream, encoding); - } - // this.redirectTriggers = redirectTriggers; } + // this.redirectTriggers = redirectTriggers; + } - /** - * All startElement events occuring in the redirectTriggers list will trigger - * redirection of the entire (sub-)fragment. - * - * @param event - * @return false if an event is redirected - */ - @Override - public boolean accept(XMLEvent event) { - int eventType = event.getEventType(); + /** + * All startElement events occuring in the redirectTriggers list will trigger + * redirection of the entire (sub-)fragment. + * + * @param event + * @return false if an event is redirected + */ + @Override + public boolean accept(XMLEvent event) { + int eventType = event.getEventType(); - if (eventType == XMLStreamConstants.START_ELEMENT) { - currentNamespaceContext = event.asStartElement().getNamespaceContext(); - } - if (redirectWriter == null) { - return true; - } - if (eventType == XMLStreamConstants.START_ELEMENT) { - if (depth >= 0 || triggersRedirect(event.asStartElement().getName())) { - depth++; - } - } else if (eventType == XMLStreamConstants.END_ELEMENT) { - if (depth >= 0 && --depth < 0) { - // redirect the end element of the trigger, - // but do not redirect the end element of the calling type - if (redirectTriggers != null) { - redirectEvent(event); - return false; - } - } - } - if (depth >= 0) { //|| (depth == 0 && redirectTriggers == null)) { - redirectEvent(event); - return false; + if (eventType == XMLStreamConstants.START_ELEMENT) { + //hopefully, this is a copy + currentNamespaceContext = event.asStartElement().getNamespaceContext(); + } + if (redirectWriter == null) { + return true; + } + if (eventType == XMLStreamConstants.START_ELEMENT) { + if (depth >= 0 || triggersRedirect(event.asStartElement().getName())) { + depth++; + } + } else if (eventType == XMLStreamConstants.END_ELEMENT) { + if (depth >= 0 && --depth < 0) { + // redirect the end element of the trigger, + // but do not redirect the end element of the calling type + if (redirectTriggers != null) { + redirectEvent(event); + return false; } - return true; // depth < 0; + } + } + if (depth >= 0) { //|| (depth == 0 && redirectTriggers == null)) { + redirectEvent(event); + return false; + } + return true; // depth < 0; // switch (event.getEventType()) { // case XMLStreamConstants.START_ELEMENT: @@ -132,128 +137,130 @@ public class RedirectEventFilter implements EventFilter { // return false; // } // return true; // depth < 0; - } + } - /** - * @param startElt - * @return true if the set of triggers contains startElement - * (or no triggers are registered, i.e. everything is redirected) - */ - private boolean triggersRedirect(QName startElement) { - if (redirectTriggers != null) { - return redirectTriggers.contains(startElement); - } - return true; + /** + * @param startElt + * @return true if the set of triggers contains startElement + * (or no triggers are registered, i.e. everything is redirected) + */ + private boolean triggersRedirect(QName startElement) { + if (redirectTriggers != null) { + return redirectTriggers.contains(startElement); } + return true; + } - private void redirectEvent(XMLEvent event) { - try { - if (log.isTraceEnabled()) { - log.trace("redirecting StAX event " + event); - } - redirectWriter.add(event); - } catch (XMLStreamException ex) { - ex.printStackTrace(); - } + private void redirectEvent(XMLEvent event) { + try { + if (log.isTraceEnabled()) { + log.trace("redirecting StAX event " + event); + } + redirectWriter.add(event); + } catch (XMLStreamException ex) { + ex.printStackTrace(); } + } - /** - * Enable/disable redirection of all events from now on. - * The redirected events will be UTF-8 encoded and written to the stream. - * - * @param redirectstream - * if null, redirection is disabled - */ - public void setRedirectStream(OutputStream redirectStream) throws XMLStreamException { - setRedirectStream(redirectStream, DEFAULT_ENCODING, null); - } + /** + * Enable/disable redirection of all events from now on. + * The redirected events will be UTF-8 encoded and written to the stream. + * + * @param redirectstream + * if null, redirection is disabled + */ + public void setRedirectStream(OutputStream redirectStream) throws XMLStreamException { + setRedirectStream(redirectStream, DEFAULT_ENCODING, null); + } - /** - * Enable/disable redirection of all events from now on. - * - * @param redirectStream if null, redirection is disabled - * @param encoding The encoding for the redirect stream - * @throws javax.xml.stream.XMLStreamException - */ - public void setRedirectStream(OutputStream redirectStream, String encoding) throws XMLStreamException { - setRedirectStream(redirectStream, encoding, null); - } + /** + * Enable/disable redirection of all events from now on. + * + * @param redirectStream if null, redirection is disabled + * @param encoding The encoding for the redirect stream + * @throws javax.xml.stream.XMLStreamException + */ + public void setRedirectStream(OutputStream redirectStream, String encoding) throws XMLStreamException { + setRedirectStream(redirectStream, encoding, null); + } - /** - * Enable/disable redirection of all (child) elements contained in redirect triggers. - * The redirected events will be UTF-8 encoded and written to the stream. - * - * @param redirectstream - * if null, redirection is disabled - * @param redirectTriggers elements that trigger the redirection - */ - public void setRedirectStream(OutputStream redirectStream, Set redirectTriggers) throws XMLStreamException { - setRedirectStream(redirectStream, DEFAULT_ENCODING, redirectTriggers); - } + /** + * Enable/disable redirection of all (child) elements contained in redirect triggers. + * The redirected events will be UTF-8 encoded and written to the stream. + * + * @param redirectstream + * if null, redirection is disabled + * @param redirectTriggers elements that trigger the redirection + */ + public void setRedirectStream(OutputStream redirectStream, Set redirectTriggers) throws XMLStreamException { + setRedirectStream(redirectStream, DEFAULT_ENCODING, redirectTriggers); + } - /** - * Enable/disable redirection of all (child) elements contained in redirect triggers. - * - * @param redirectstream - * if null, redirection is disabled - * @param encoding The encoding for the redirect stream - * @param redirectTriggers elements that trigger the redirection - */ - public void setRedirectStream(OutputStream redirectStream, String encoding, Set redirectTriggers) throws XMLStreamException { - if (redirectStream != null) { - XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); - if (encoding == null) { - encoding = DEFAULT_ENCODING; - } - redirectWriter = outputFactory.createXMLEventWriter(redirectStream, + /** + * Enable/disable redirection of all (child) elements contained in redirect triggers. + * + * TODO: don't set redirect stream from caller (caller does not know whether redirection will be triggered) + * rather create on trigger and pass to caller + * @param redirectstream + * if null, redirection is disabled + * @param encoding The encoding for the redirect stream + * @param redirectTriggers elements that trigger the redirection + */ + public void setRedirectStream(OutputStream redirectStream, String encoding, Set redirectTriggers) throws XMLStreamException { + if (redirectStream != null) { + XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); + if (encoding == null) { + encoding = DEFAULT_ENCODING; + } + redirectWriter = outputFactory.createXMLEventWriter(redirectStream, encoding); - if (redirectTriggers == null) { - // start redirecting - depth = 0; - } - this.redirectTriggers = redirectTriggers; - } else { - redirectWriter = null; - this.redirectTriggers = null; - } + if (redirectTriggers == null) { + // start redirecting + depth = 0; + } + this.redirectTriggers = redirectTriggers; + } else { + redirectWriter = null; + this.redirectTriggers = null; } + } - /** - * Enable/disable redirection of fragments (defined by elements in - * redirectTriggers) - * - * @param redirectStream - * if null, redirection is disabled - * @param redirectTriggers - * All startElement events occuring in this list will trigger - * redirection of the entire fragment. If null, all events are - * redirected - */ - // public void setRedirectStream(OutputStream redirectStream, List - // redirectTriggers) throws XMLStreamException { - // if (redirectStream != null) { - // XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); - // redirectWriter = outputFactory.createXMLEventWriter(redirectStream); - // } else { - // redirectWriter = null; - // } - // this.redirectTriggers = (redirectStream == null) ? null : redirectTriggers; - // } - /** - * flushes the internal EventWriter - * - * @throws javax.xml.stream.XMLStreamException - */ - public void flushRedirectStream() throws XMLStreamException { - redirectWriter.flush(); - } + /** + * Enable/disable redirection of fragments (defined by elements in + * redirectTriggers) + * + * @param redirectStream + * if null, redirection is disabled + * @param redirectTriggers + * All startElement events occuring in this list will trigger + * redirection of the entire fragment. If null, all events are + * redirected + */ + // public void setRedirectStream(OutputStream redirectStream, List + // redirectTriggers) throws XMLStreamException { + // if (redirectStream != null) { + // XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); + // redirectWriter = outputFactory.createXMLEventWriter(redirectStream); + // } else { + // redirectWriter = null; + // } + // this.redirectTriggers = (redirectStream == null) ? null : redirectTriggers; + // } + /** + * flushes the internal EventWriter + * + * @throws javax.xml.stream.XMLStreamException + */ + public void flushRedirectStream() throws XMLStreamException { + redirectWriter.flush(); + } - /** - * the namespaceContext of the last startelement event read - * - * @return - */ - public NamespaceContext getCurrentNamespaceContext() { - return currentNamespaceContext; - } + /** + * the namespaceContext of the last startelement event read + * + * @return + */ + public NamespaceContext getCurrentNamespaceContext() { + return currentNamespaceContext; + } } diff --git a/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java b/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java index b4e988f0..1180e9fa 100644 --- a/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java +++ b/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java @@ -25,6 +25,7 @@ import java.io.ByteArrayOutputStream; import java.util.HashSet; import java.util.Set; import javax.xml.bind.annotation.XmlTransient; +import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import org.apache.commons.logging.Log; diff --git a/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java b/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java index c32542aa..eb147f88 100644 --- a/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java +++ b/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java @@ -35,7 +35,7 @@ import org.apache.commons.logging.LogFactory; public class XMLContentType extends at.buergerkarte.namespaces.securitylayer._1.XMLContentType implements RedirectCallback { @XmlTransient - private static Log log = LogFactory.getLog(TransformsInfoType.class); + private static Log log = LogFactory.getLog(XMLContentType.class); @XmlTransient protected ByteArrayOutputStream redirectOS = null; diff --git a/utils/src/main/java/org/w3/_2000/_09/xmldsig_/ObjectFactory.java b/utils/src/main/java/org/w3/_2000/_09/xmldsig_/ObjectFactory.java index 4ab376f1..fae77451 100644 --- a/utils/src/main/java/org/w3/_2000/_09/xmldsig_/ObjectFactory.java +++ b/utils/src/main/java/org/w3/_2000/_09/xmldsig_/ObjectFactory.java @@ -167,6 +167,7 @@ public class ObjectFactory { * */ public TransformType createTransformType() { +// return new at.gv.egiz.slbinding.impl.TransformType(); return new TransformType(); } diff --git a/utils/src/main/java/org/w3/_2000/_09/xmldsig_/TransformsType.java b/utils/src/main/java/org/w3/_2000/_09/xmldsig_/TransformsType.java index 584baf80..c7044c4c 100644 --- a/utils/src/main/java/org/w3/_2000/_09/xmldsig_/TransformsType.java +++ b/utils/src/main/java/org/w3/_2000/_09/xmldsig_/TransformsType.java @@ -57,7 +57,7 @@ import javax.xml.bind.annotation.XmlType; }) public class TransformsType { - @XmlElement(name = "Transform", required = true) + @XmlElement(name = "Transform", required = true) //, type=at.gv.egiz.slbinding.impl.TransformType.class) protected List transform; /** diff --git a/utils/src/test/java/at/gv/egiz/slbinding/RedirectTest.java b/utils/src/test/java/at/gv/egiz/slbinding/RedirectTest.java index 99d353ac..7c8c206a 100644 --- a/utils/src/test/java/at/gv/egiz/slbinding/RedirectTest.java +++ b/utils/src/test/java/at/gv/egiz/slbinding/RedirectTest.java @@ -52,6 +52,8 @@ import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import static org.junit.Assert.*; +import org.w3._2000._09.xmldsig_.TransformType; +import org.w3._2000._09.xmldsig_.TransformsType; /** * @@ -131,11 +133,34 @@ public class RedirectTest { Iterator tiIt = transformsInfos.iterator(); while (tiIt.hasNext()) { at.gv.egiz.slbinding.impl.TransformsInfoType ti = (at.gv.egiz.slbinding.impl.TransformsInfoType) tiIt.next(); +// TransformsInfoType ti = tiIt.next(); assertNotNull(ti); - System.out.println("found at.gv.egiz.slbinding.impl.TransformsInfoType TransformsInfo"); + System.out.println("found sl:TransformsInfo: " + ti.getClass().getName()); //at.gv.egiz.slbinding.impl.TransformsInfoType TransformsInfo"); +// TransformsType ts = ti.getTransforms(); +// assertNotNull(ts); +// System.out.println("found dsig:Transforms " + ts.getClass().getName()); //org.w3._2000._09.xmldsig_.TransformsType dsig:Transforms"); +// List tL = ts.getTransform(); +// assertNotNull(tL); +// System.out.println("found " + tL.size() + " org.w3._2000._09.xmldsig_.TransformType dsig:Transform"); +// for (TransformType t : tL) { +// if (t instanceof at.gv.egiz.slbinding.impl.TransformType) { +// System.out.println("found at.gv.egiz.slbinding.impl.TransformType"); +// byte[] redirectedBytes = ((at.gv.egiz.slbinding.impl.TransformType) t).getRedirectedStream().toByteArray(); +// if (redirectedBytes != null && redirectedBytes.length > 0) { +// System.out.println("reading redirected stream..."); +// os.write("--- redirected Transform ---".getBytes()); +// os.write(redirectedBytes); +// os.write("\n".getBytes()); +// } else { +// System.out.println("no redirected stream"); +// } +// } +// } + ByteArrayOutputStream dsigTransforms = ti.getRedirectedStream(); + os.write("--- redirected TransformsInfo content ---".getBytes()); os.write(dsigTransforms.toByteArray()); - os.write("\n".getBytes()); + os.write("\n---".getBytes()); MetaInfoType mi = ti.getFinalDataMetaInfo(); assertNotNull(mi); diff --git a/utils/src/test/requests/CreateXMLSignatureRequest02.xml_redirect.txt b/utils/src/test/requests/CreateXMLSignatureRequest02.xml_redirect.txt index 31be50b7..fc0e4f14 100644 --- a/utils/src/test/requests/CreateXMLSignatureRequest02.xml_redirect.txt +++ b/utils/src/test/requests/CreateXMLSignatureRequest02.xml_redirect.txt @@ -1,4 +1,4 @@ - +--- redirected TransformsInfo content --- @@ -82,7 +82,7 @@ - +------ redirected TransformsInfo content --- @@ -162,3 +162,4 @@ +--- \ No newline at end of file -- 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 'BKUAppletExt/src/test') 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 22001c93bca360d1b15c252cb22d2a4147ff350d Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 20 Aug 2009 16:24:55 +0000 Subject: [#430] Activation/PIN-management in MOCCA Web Start - new Modules: smccSTALExt, BKUGuiExt in order not to depend on BKUAppletExt in BKULocal - provide stal-request handler de-registration in abstractSMCCSTAL git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@448 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- BKUApplet/src/main/java/META-INF/MANIFEST.MF | 3 - BKUAppletExt/pom.xml | 10 + .../java/at/gv/egiz/bku/gui/ActivationGUI.java | 249 -------- .../at/gv/egiz/bku/gui/ActivationGUIFacade.java | 33 - .../main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java | 70 --- .../java/at/gv/egiz/bku/gui/PINManagementGUI.java | 669 -------------------- .../at/gv/egiz/bku/gui/PINManagementGUIFacade.java | 117 ---- .../java/at/gv/egiz/bku/gui/PINSpecRenderer.java | 39 -- .../java/at/gv/egiz/bku/gui/PINStatusRenderer.java | 61 -- .../at/gv/egiz/bku/gui/PINStatusTableModel.java | 58 -- .../egiz/bku/online/applet/ActivationApplet.java | 2 +- .../bku/online/applet/PINManagementBKUWorker.java | 16 +- .../bku/smccstal/ext/CardMgmtRequestHandler.java | 177 ------ .../bku/smccstal/ext/GetPINStatusException.java | 41 -- .../smccstal/ext/ManagementPINProviderFactory.java | 262 -------- .../smccstal/ext/PINManagementRequestHandler.java | 244 -------- .../gv/egiz/bku/gui/ActivationMessages.properties | 69 --- .../egiz/bku/gui/ActivationMessages_en.properties | 68 --- .../java/at/gv/egiz/bku/gui/ActivationGuiTest.java | 62 -- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 202 ------- BKUCommonGUI/pom.xml | 2 +- .../main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java | 2 +- BKUGuiExt/pom.xml | 27 + .../java/at/gv/egiz/bku/gui/ActivationGUI.java | 250 ++++++++ .../at/gv/egiz/bku/gui/ActivationGUIFacade.java | 34 ++ .../main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java | 71 +++ .../java/at/gv/egiz/bku/gui/PINManagementGUI.java | 670 +++++++++++++++++++++ .../at/gv/egiz/bku/gui/PINManagementGUIFacade.java | 118 ++++ .../java/at/gv/egiz/bku/gui/PINSpecRenderer.java | 39 ++ .../java/at/gv/egiz/bku/gui/PINStatusRenderer.java | 61 ++ .../at/gv/egiz/bku/gui/PINStatusTableModel.java | 58 ++ .../gv/egiz/bku/gui/ActivationMessages.properties | 69 +++ .../egiz/bku/gui/ActivationMessages_en.properties | 68 +++ .../java/at/gv/egiz/bku/gui/ActivationGuiTest.java | 63 ++ .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 203 +++++++ BKULocal/pom.xml | 25 +- .../java/at/gv/egiz/bku/local/gui/GUIProxy.java | 55 ++ .../at/gv/egiz/bku/local/stal/BKUGuiProxy.java | 156 ----- .../at/gv/egiz/bku/local/stal/LocalBKUWorker.java | 6 +- .../gv/egiz/bku/local/stal/LocalSTALFactory.java | 18 +- .../bku/local/webapp/PINManagementServlet.java | 167 +++++ BKULocal/src/main/webapp/WEB-INF/web.xml | 10 +- BKULocal/src/main/webapp/index.html | 7 +- .../java/at/gv/egiz/bku/webstart/Launcher.java | 104 +++- .../bku/webstart/gui/PINManagementInvoker.java | 71 +++ .../gv/egiz/bku/webstart/gui/TrayMenuListener.java | 75 --- BKUWebStart/src/main/jnlp/resources/version.xml | 12 +- .../at/gv/egiz/bku/webstart/messages.properties | 1 + pom.xml | 2 + .../at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java | 5 + smccSTALExt/pom.xml | 27 + .../egiz/bku/smccstal/CardMgmtRequestHandler.java | 177 ++++++ .../egiz/bku/smccstal/GetPINStatusException.java | 41 ++ .../bku/smccstal/ManagementPINProviderFactory.java | 262 ++++++++ .../bku/smccstal/PINManagementRequestHandler.java | 245 ++++++++ 55 files changed, 2947 insertions(+), 2706 deletions(-) delete mode 100644 BKUApplet/src/main/java/META-INF/MANIFEST.MF delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/CardMgmtRequestHandler.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/GetPINStatusException.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java delete mode 100644 BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java delete mode 100644 BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties delete mode 100644 BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties delete mode 100644 BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java delete mode 100644 BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java create mode 100644 BKUGuiExt/pom.xml create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java create mode 100644 BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java create mode 100644 BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties create mode 100644 BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties create mode 100644 BKUGuiExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java create mode 100644 BKUGuiExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java create mode 100644 BKULocal/src/main/java/at/gv/egiz/bku/local/gui/GUIProxy.java delete mode 100644 BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java create mode 100644 BKULocal/src/main/java/at/gv/egiz/bku/local/webapp/PINManagementServlet.java create mode 100644 BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java delete mode 100644 BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/TrayMenuListener.java create mode 100644 smccSTALExt/pom.xml create mode 100644 smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/CardMgmtRequestHandler.java create mode 100644 smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/GetPINStatusException.java create mode 100644 smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/ManagementPINProviderFactory.java create mode 100644 smccSTALExt/src/main/java/at/gv/egiz/bku/smccstal/PINManagementRequestHandler.java (limited to 'BKUAppletExt/src/test') diff --git a/BKUApplet/src/main/java/META-INF/MANIFEST.MF b/BKUApplet/src/main/java/META-INF/MANIFEST.MF deleted file mode 100644 index 5e949512..00000000 --- a/BKUApplet/src/main/java/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/BKUAppletExt/pom.xml b/BKUAppletExt/pom.xml index 79fc5600..98502ab2 100644 --- a/BKUAppletExt/pom.xml +++ b/BKUAppletExt/pom.xml @@ -31,6 +31,16 @@ BKUApplet 1.2.2-SNAPSHOT + + at.gv.egiz + BKUGuiExt + 1.2.2-SNAPSHOT + + + at.gv.egiz + smccSTALExt + 1.2.2-SNAPSHOT + diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java deleted file mode 100644 index 8134ac5f..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java +++ /dev/null @@ -1,249 +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 java.awt.Container; -import java.awt.Cursor; -import java.awt.event.ActionListener; -import java.net.URL; -import java.text.MessageFormat; -import java.util.Locale; -import java.util.ResourceBundle; -import javax.swing.GroupLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JProgressBar; -import javax.swing.LayoutStyle; -import javax.swing.SwingUtilities; - -/** - * - * @author Clemens Orthacker - */ -public class ActivationGUI extends CardMgmtGUI implements ActivationGUIFacade { - - public static final String TITLE_ACTIVATION = "title.activation"; - public static final String LABEL_ACTIVATION = "label.activation"; - public static final String LABEL_ACTIVATION_STEP = "label.activation.step"; - public static final String LABEL_ACTIVATION_IDLE = "label.activation.idle"; - - public static final String HELP_ACTIVATION = "help.activation"; - - protected JProgressBar progressBar; - - public ActivationGUI(Container contentPane, - Locale locale, - Style guiStyle, - URL backgroundImgURL, - AbstractHelpListener helpListener) { - super(contentPane, locale, guiStyle, backgroundImgURL, helpListener); - - progressBar = new JProgressBar(); - } - - @Override - public void showActivationProgressDialog(final int currentStep, final int maxProgress, final ActionListener cancelListener, final String cancelCommand) { - - log.debug("scheduling activation progress dialog (step " + currentStep + ")"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show activation progress dialog (step " + currentStep + ")"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - mainPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - - - JLabel infoLabel = new JLabel(); - infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - - if (renderHeaderPanel) { - titleLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); - infoLabel.setText(cardmgmtMessages.getString(LABEL_ACTIVATION)); - } else { - infoLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); - } - - helpListener.setHelpTopic(HELP_ACTIVATION); - - progressBar.setIndeterminate(false); - progressBar.setStringPainted(true); - progressBar.setString(null); //reset to percentage - progressBar.setMinimum(0); - progressBar.setMaximum(maxProgress); - - JLabel stepLabel = new JLabel(); - stepLabel.setFont(stepLabel.getFont().deriveFont(stepLabel.getFont().getStyle() & ~java.awt.Font.BOLD, stepLabel.getFont().getSize()-2)); - String stepPattern = cardmgmtMessages.getString(LABEL_ACTIVATION_STEP); - stepLabel.setText(MessageFormat.format(stepPattern, new Object[]{ currentStep })); - - 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) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(stepLabel) - .addComponent(progressBar))); - - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(infoVertical) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(stepLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(progressBar))); - - JButton cancelButton = new JButton(); - cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - 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(); - - } - }); - - } - - @Override - public void incrementProgress() { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - progressBar.setValue(progressBar.getValue() + 1); - } - }); - - } - - @Override - public void showIdleDialog(final ActionListener cancelListener, final String cancelCommand) { - log.debug("scheduling idle dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - log.debug("show idle dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - mainPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - - - JLabel infoLabel = new JLabel(); - infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - - if (renderHeaderPanel) { - titleLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); - infoLabel.setText(cardmgmtMessages.getString(LABEL_ACTIVATION)); - } else { - infoLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); - } - - helpListener.setHelpTopic(HELP_ACTIVATION); - - progressBar.setIndeterminate(true); - progressBar.setStringPainted(true); - progressBar.setString(""); //not string painted progressbar is smaller - - JLabel stepLabel = new JLabel(); - stepLabel.setFont(stepLabel.getFont().deriveFont(stepLabel.getFont().getStyle() & ~java.awt.Font.BOLD, stepLabel.getFont().getSize()-2)); - stepLabel.setText(cardmgmtMessages.getString(LABEL_ACTIVATION_IDLE)); - - 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) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(stepLabel) - .addComponent(progressBar))); - - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(infoVertical) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(stepLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(progressBar))); - - JButton cancelButton = new JButton(); - cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - 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(); - - } - }); - - } -} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java deleted file mode 100644 index 860a1097..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java +++ /dev/null @@ -1,33 +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 java.awt.event.ActionListener; - -/** - * - * @author Clemens Orthacker - */ -public interface ActivationGUIFacade extends BKUGUIFacade { - - public void showActivationProgressDialog(int currentStep, int maxProgress, ActionListener cancelListener, String cancelCommand); - - public void incrementProgress(); - - public void showIdleDialog(ActionListener cancelListener, String cancelCommand); - -} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java deleted file mode 100644 index ac9ab78b..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java +++ /dev/null @@ -1,70 +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 java.awt.Container; -import java.net.URL; -import java.util.Locale; -import java.util.ResourceBundle; - -/** - * Common superclass for Activation and PinManagement GUIs - * - * @author Clemens Orthacker - */ -public class CardMgmtGUI extends BKUGUIImpl { - - public static final String CARDMGMT_MESSAGES_BUNDLE = "at/gv/egiz/bku/gui/ActivationMessages"; - - protected ResourceBundle cardmgmtMessages; - - public CardMgmtGUI(Container contentPane, - Locale locale, - Style guiStyle, - URL backgroundImgURL, - AbstractHelpListener helpListener) { - super(contentPane, locale, guiStyle, backgroundImgURL, helpListener); - - } - - @Override - protected void loadMessageBundle(Locale locale) { - super.loadMessageBundle(locale); - - if (locale != null) { - Locale lang = new Locale(locale.getLanguage().substring(0,2)); - log.debug("loading applet resources for language: " + lang.toString()); - cardmgmtMessages = ResourceBundle.getBundle(CARDMGMT_MESSAGES_BUNDLE, lang); - } else { - cardmgmtMessages = ResourceBundle.getBundle(CARDMGMT_MESSAGES_BUNDLE); - } - } - - @Override - protected String getMessage(String key) { - if (super.hasMessage(key)) { - return super.getMessage(key); - } - return cardmgmtMessages.getString(key); - } - - @Override - protected boolean hasMessage(String key) { - return (cardmgmtMessages.containsKey(key) || super.hasMessage(key)); - } -} 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 deleted file mode 100644 index 3b77daa5..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java +++ /dev/null @@ -1,669 +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.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; -import java.awt.event.MouseMotionAdapter; -import java.net.URL; -import java.text.MessageFormat; -import java.util.Locale; -import java.util.Map; -import javax.swing.GroupLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -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 org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * TODO pull out ResourceBundle to common superclass for activationGUI and pinMgmtGUI - * @author Clemens Orthacker - */ -public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFacade { - - protected static final Log log = LogFactory.getLog(PINManagementGUI.class); - - /** remember the pinfield to return to worker */ - protected JPasswordField oldPinField; - /** remember the pinSpec to return to worker */ - protected PINSpec pinSpec; - - public PINManagementGUI(Container contentPane, - Locale locale, - Style guiStyle, - URL backgroundImgURL, - AbstractHelpListener helpListener) { - super(contentPane, locale, guiStyle, backgroundImgURL, helpListener); - } - - @Override - public char[] getOldPin() { - if (oldPinField != null) { - char[] pin = oldPinField.getPassword(); - oldPinField = null; - return pin; - } - return null; - } - - @Override - public PINSpec getSelectedPINSpec() { - return pinSpec; - } - - @Override - public void showPINManagementDialog(final Map pins, - final ActionListener activateListener, - final String activateCmd, - final String changeCmd, - final String unblockCmd, - final String verifyCmd, - final ActionListener cancelListener, - final String cancelCmd) { - - log.debug("scheduling PIN managment dialog"); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - log.debug("show PIN management dialog"); - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - helpListener.setHelpTopic(HELP_PINMGMT); - - JLabel mgmtLabel = new JLabel(); - mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - - if (renderHeaderPanel) { - titleLabel.setText(getMessage(TITLE_PINMGMT)); - String infoPattern = getMessage(MESSAGE_PINMGMT); - mgmtLabel.setText(MessageFormat.format(infoPattern, pins.size())); - } else { - mgmtLabel.setText(getMessage(TITLE_PINMGMT)); - } - - final PINStatusTableModel tableModel = new PINStatusTableModel(pins); - final JTable pinStatusTable = new JTable(tableModel); - pinStatusTable.setDefaultRenderer(PINSpec.class, new PINSpecRenderer()); - pinStatusTable.setDefaultRenderer(STATUS.class, new PINStatusRenderer(cardmgmtMessages)); - pinStatusTable.setTableHeader(null); - 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)); - activateButton.addActionListener(activateListener); - - pinStatusTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - pinStatusTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - - @Override - public void valueChanged(final ListSelectionEvent e) { - //invoke later to allow thread to paint selection background - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - ListSelectionModel lsm = (ListSelectionModel) e.getSource(); - int selectionIdx = lsm.getMinSelectionIndex(); - if (selectionIdx >= 0) { - pinSpec = (PINSpec) tableModel.getValueAt(selectionIdx, 0); - STATUS status = (STATUS) tableModel.getValueAt(selectionIdx, 1); - - if (status == STATUS.NOT_ACTIV) { - activateButton.setText(getMessage(BUTTON_ACTIVATE)); - activateButton.setEnabled(true); - activateButton.setActionCommand(activateCmd); - } else if (status == STATUS.BLOCKED) { - activateButton.setText(getMessage(BUTTON_UNBLOCK)); - activateButton.setEnabled(true); - activateButton.setActionCommand(unblockCmd); - } else if (status == STATUS.ACTIV) { - activateButton.setText(getMessage(BUTTON_CHANGE)); - activateButton.setEnabled(true); - activateButton.setActionCommand(changeCmd); - } else if (status == STATUS.UNKNOWN) { - activateButton.setText(getMessage(BUTTON_VERIFY)); - activateButton.setEnabled(true); - activateButton.setActionCommand(verifyCmd); - } - } - } - }); - } - }); - - //select first entry - pinStatusTable.getSelectionModel().setSelectionInterval(0, 0); - - JScrollPane pinStatusScrollPane = new JScrollPane(pinStatusTable); - - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - - GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() - .addComponent(mgmtLabel); - GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(mgmtLabel); - if (!renderHeaderPanel) { - messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); - } - - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(messageHorizontal) - .addComponent(pinStatusScrollPane, 0, 0, Short.MAX_VALUE)); - - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(messageVertical) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinStatusScrollPane, 0, 0, pinStatusTable.getPreferredSize().height+3)); - - JButton cancelButton = new JButton(); - cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); - cancelButton.setText(getMessage(BUTTON_CLOSE)); - cancelButton.setActionCommand(cancelCmd); - cancelButton.addActionListener(cancelListener); - - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(activateButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); - - GroupLayout.Group buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(activateButton) - .addComponent(cancelButton); - - buttonPanelLayout.setHorizontalGroup(buttonHorizontal); - buttonPanelLayout.setVerticalGroup(buttonVertical); - - contentPanel.validate(); - } - }); - } - - @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) { - String title, msg; - Object[] params; - if (retries < 0) { - params = new Object[2]; - if (shortText) { - params[0] = "PIN"; - } else { - params[0] = pinSpec.getLocalizedName(); - } - params[1] = pinSpec.getLocalizedLength(); - 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, MESSAGE_MGMT_PARAM, PINSIZE; - HELP_TOPIC = HELP_PINMGMT; - - PINSIZE = (pinSpec.getMaxLength() > pinSpec.getMinLength()) ? - pinSpec.getMinLength() + "-" + pinSpec.getMaxLength() : - String.valueOf(pinSpec.getMinLength()); - - 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; - PINSIZE = pinSpec.getLocalizedLength(); - } 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 retry pin dialog"); - TITLE = TITLE_RETRY; - MESSAGE_MGMT = (retries < 2) ? - MESSAGE_LAST_RETRY : MESSAGE_RETRIES; - MESSAGE_MGMT_PARAM = String.valueOf(retries); - } - - mainPanel.removeAll(); - buttonPanel.removeAll(); - - helpListener.setHelpTopic(HELP_TOPIC); - - JLabel mgmtLabel = new JLabel(); - 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); - mgmtLabel.setText(MessageFormat.format(mgmtPattern, MESSAGE_MGMT_PARAM)); - } else { - mgmtLabel.setText(getMessage(TITLE)); - } - - //////////////////////////////////////////////////////////////// - // 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_VERIFYPIN_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(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() & ~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.setActionCommand(okCommand); - pinField.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(); - } - } - } - }); - - 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 (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(); - } - } - }); - - 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)); - } - - JLabel pinsizeLabel = new JLabel(); - pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~Font.BOLD, pinsizeLabel.getFont().getSize()-2)); - String pinsizePattern = getMessage(LABEL_PINSIZE); - pinsizeLabel.setText(MessageFormat.format(pinsizePattern, new Object[]{PINSIZE})); - - //////////////////////////////////////////////////////////////// - // NON-PINPAD SPECIFIC LAYOUT SECTION - //////////////////////////////////////////////////////////////// - - pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); - 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 (type == DIALOG.CHANGE) { - pinHorizontal - .addGroup(mainPanelLayout.createSequentialGroup() - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(oldPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); - - pinVertical - .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 if (type == DIALOG.ACTIVATE) { - pinHorizontal - .addGroup(mainPanelLayout.createSequentialGroup() - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); - - pinVertical - .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 { // 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); - - 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) - .addGroup(infoHorizontal) - .addGroup(pinHorizontal)); - - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createSequentialGroup() - .addGroup(infoVertical) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pinVertical)); - - contentPanel.validate(); - - } - }); - } - - @Override - protected int initButtonSize() { - int bs = super.initButtonSize(); - - JButton b = new JButton(); - b.setText(getMessage(BUTTON_ACTIVATE)); - if (b.getPreferredSize().width > bs) { - bs = b.getPreferredSize().width; - } - b.setText(getMessage(BUTTON_CHANGE)); - if (b.getPreferredSize().width > bs) { - bs = b.getPreferredSize().width; - } - b.setText(getMessage(BUTTON_UNBLOCK)); - if (b.getPreferredSize().width > bs) { - bs = b.getPreferredSize().width; - } - b.setText(getMessage(BUTTON_CANCEL)); - if (b.getPreferredSize().width > bs) { - bs = b.getPreferredSize().width; - } - - return bs; - } - -} 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 deleted file mode 100644 index f99bcfd1..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ /dev/null @@ -1,117 +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.smcc.PINSpec; -import java.awt.event.ActionListener; -import java.util.Map; - -/** - * - * @author Clemens Orthacker - */ -public interface PINManagementGUIFacade extends BKUGUIFacade { - - public static final String HELP_PINMGMT = "help.pin.mgmt"; -// public static final String HELP_VERIFY_PIN = "help.pin.verify"; - 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"; - - // 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_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"; - - 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 ERR_PIN_FORMAT = "err.pin.format"; - public static final String ERR_PIN_CONFIRMATION = "err.pin.confirmation"; - public static final String ERR_PIN_OPERATION_ABORTED = "err.pin.operation.aborted"; - public static final String ERR_UNSUPPORTED_CARD = "err.unsupported.card"; - - 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"; - public static final String STATUS_NOT_ACTIVE = "status.not.active"; - 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 showPINDialog(DIALOG type, PINSpec pin, - 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); - - 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(); - - public PINSpec getSelectedPINSpec(); -} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java deleted file mode 100644 index e3d73e1f..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java +++ /dev/null @@ -1,39 +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.smcc.PINSpec; -import javax.swing.table.DefaultTableCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author Clemens Orthacker - */ -public class PINSpecRenderer extends DefaultTableCellRenderer { - - private static final Log log = LogFactory.getLog(PINSpecRenderer.class); - - @Override - protected void setValue(Object value) { - PINSpec pinSpec = (PINSpec) value; - super.setText(pinSpec.getLocalizedName()); - } - -} 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 deleted file mode 100644 index 83ff74f2..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java +++ /dev/null @@ -1,61 +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.PINManagementGUIFacade.STATUS; -import java.awt.Color; -import java.awt.Font; -import java.util.ResourceBundle; -import javax.swing.table.DefaultTableCellRenderer; - -/** - * - * @author Clemens Orthacker - */ -public class PINStatusRenderer extends DefaultTableCellRenderer { - -// private static final Log log = LogFactory.getLog(PINStatusRenderer.class); - - public static final Color RED = new Color(0.9f, 0.0f, 0.0f); - public static final Color GREEN = new Color(0.0f, 0.8f, 0.0f); - protected ResourceBundle messages; - - public PINStatusRenderer(ResourceBundle messages) { - this.messages = messages; - } - - @Override - protected void setValue(Object value) { - STATUS pinStatus = (STATUS) value; - super.setFont(super.getFont().deriveFont(super.getFont().getStyle() | Font.BOLD)); - - if (pinStatus == STATUS.NOT_ACTIV) { - super.setForeground(RED); - super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_NOT_ACTIVE) + ""); - } else if (pinStatus == STATUS.ACTIV) { - super.setForeground(GREEN); - super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_ACTIVE) + ""); - } else if (pinStatus == STATUS.BLOCKED) { - super.setForeground(RED); - super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_BLOCKED) + ""); - } else { - super.setForeground(Color.BLACK); - super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_UNKNOWN) + ""); - } - } -} 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 deleted file mode 100644 index 052c13b2..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java +++ /dev/null @@ -1,58 +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.PINManagementGUIFacade.STATUS; -import at.gv.egiz.smcc.PINSpec; -import java.util.Map; -import javax.swing.table.DefaultTableModel; - -/** - * - * @author Clemens Orthacker - */ -public class PINStatusTableModel extends DefaultTableModel { - -// protected static final Log log = LogFactory.getLog(PINStatusTableModel.class); - protected Class[] types; - - public PINStatusTableModel(Map pinStatuses) { - super(0, 2); - if (pinStatuses == null) { - throw new RuntimeException("pinStatuses must not be null"); - } -// log.trace(pinStatuses.size() + " PINs"); - types = new Class[] { PINSpec.class, STATUS.class }; - for (PINSpec pinSpec : pinStatuses.keySet()) { - addRow(new Object[] { pinSpec, pinStatuses.get(pinSpec) }); - } -// PINSpec activePIN = new PINSpec(0, 1, null, "active-PIN", (byte) 0x01); -// PINSpec blockedPIN = new PINSpec(0, 1, null, "blocked-PIN", (byte) 0x01); -// addRow(new Object[] { activePIN, PINStatusProvider.STATUS.ACTIV }); -// addRow(new Object[] { blockedPIN, PINStatusProvider.STATUS.BLOCKED }); - } - - @Override - public Class getColumnClass(int columnIndex) { - return types[columnIndex]; - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return false; - } -} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ActivationApplet.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ActivationApplet.java index 68f0cb72..cfd1e200 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ActivationApplet.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/ActivationApplet.java @@ -22,7 +22,7 @@ import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.BKUGUIFacade.Style; import at.gv.egiz.bku.online.applet.BKUApplet; import at.gv.egiz.bku.smccstal.AbstractSMCCSTAL; -import at.gv.egiz.bku.smccstal.ext.CardMgmtRequestHandler; +import at.gv.egiz.bku.smccstal.CardMgmtRequestHandler; import at.gv.egiz.stal.ext.APDUScriptRequest; import at.gv.egiz.stal.service.STALPortType; import at.gv.egiz.stal.service.translator.STALTranslator; 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 81b635f8..d06c2865 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 @@ -18,11 +18,16 @@ package at.gv.egiz.bku.online.applet; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.PINManagementGUIFacade; -import at.gv.egiz.bku.smccstal.ext.PINManagementRequestHandler; +import at.gv.egiz.bku.smccstal.PINManagementRequestHandler; 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.ext.PINManagementRequest; import at.gv.egiz.stal.ext.PINManagementResponse; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -36,7 +41,8 @@ public class PINManagementBKUWorker extends AppletBKUWorker { public PINManagementBKUWorker(BKUApplet applet, PINManagementGUIFacade gui) { super(applet, gui); - handlerMap.clear(); + removeRequestHandler(InfoboxReadRequest.class); + removeRequestHandler(SignRequest.class); addRequestHandler(PINManagementRequest.class, new PINManagementRequestHandler()); } @@ -46,7 +52,11 @@ public class PINManagementBKUWorker extends AppletBKUWorker { BKUGUIFacade.MESSAGE_WELCOME); try { - List responses = handleRequest(Collections.singletonList(new PINManagementRequest())); + + ArrayList reqs = new ArrayList(); + reqs.add(new PINManagementRequest()); + reqs.add(new QuitRequest()); + List responses = handleRequest(reqs); if (responses.size() == 1) { STALResponse response = responses.get(0); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/CardMgmtRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/CardMgmtRequestHandler.java deleted file mode 100644 index 769342e7..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/CardMgmtRequestHandler.java +++ /dev/null @@ -1,177 +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.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/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 deleted file mode 100644 index abbe66a1..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/GetPINStatusException.java +++ /dev/null @@ -1,41 +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.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/ManagementPINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java deleted file mode 100644 index f54f89d4..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java +++ /dev/null @@ -1,262 +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.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/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 deleted file mode 100644 index e0b09d63..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java +++ /dev/null @@ -1,244 +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 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)) { - 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); - } - } - -} 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 deleted file mode 100644 index 977d6e3a..00000000 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ /dev/null @@ -1,69 +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. - -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.success=Erfolg -title.change.success=Erfolg - -# removed message.* prefix to reuse keys as help keys -pin.mgmt=Die Karte verf\u00FCgt \u00FCber {0} PINs -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. - -label.activation=e-card Aktivierungsprozess -label.activation.step=Schritt {0} -label.activation.idle=Warte auf Server... -label.old.pin=Alte {0}: -label.new.pin=Neue {0}: -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=Falsche {0}, noch {1} Versuche -err.locked={0} gesperrt. -err.not.active={0} nicht aktiviert. -err.pin.format=Ung\u00FCltige {0} L\u00E4nge, verlangt sind {1} Stellen. -err.pin.confirmation={0} und Best\u00E4tigung stimmen nicht \u00FCberein. -err.pin.operation.aborted=Der Vorgang f\u00FCr {0} wurde abgebrochen. -err.unsupported.card=Die Karte wird nicht unterst\u00FCtzt - -status.not.active=NICHT AKTIV -status.active=AKTIV -status.blocked=GESPERRT -status.unknown=UNBEKANNT 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 deleted file mode 100644 index 7f01971b..00000000 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ /dev/null @@ -1,68 +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. - -title.activation=Activation -title.pin.mgmt=PIN Management -title.activate.pin=Activate PIN -title.verify.pin=Enter PIN -title.change.pin=Change PIN -title.unblock.pin=Unblock PIN -title.activate.success=Success -title.change.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). -activate.success={0} successfully activated -change.success={0} successfully changed - -label.activation=e-card activation process -label.activation.step=Step {0} -label.activation.idle=Wait for server... -label.old.pin=Old {0}: -label.new.pin=New {0}: -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. -err.pin.format=Invalid {0} length, {1} digit(s) required. -err.pin.confirmation={0} and confirmation do not match. -err.pin.operation.aborted=The operation on {0} was aborted. -err.unsupported.card=This card is not supported - -status.not.active=NOT ACTIVE -status.active=ACTIVE -status.blocked=BLOCKED -status.unknown=UNKNOWN diff --git a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java deleted file mode 100644 index 95c5c678..00000000 --- a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java +++ /dev/null @@ -1,62 +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. -*/ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -package at.gv.egiz.bku.gui; - -import java.awt.Container; -import java.awt.Dimension; -import javax.swing.JFrame; -import org.junit.Ignore; -import org.junit.Test; - - -/** - * - * @author clemens - */ -@Ignore -public class ActivationGuiTest { - - @Test - public void testBKUGUI() { - JFrame testFrame = new JFrame("BKUGUITest"); - Container contentPane = testFrame.getContentPane(); - contentPane.setPreferredSize(new Dimension(152, 145)); -// contentPane.setPreferredSize(new Dimension(300, 190)); - ActivationGUIFacade gui = new ActivationGUI(contentPane, null, BKUGUIFacade.Style.tiny, null, null); - BKUGUIWorker worker = new BKUGUIWorker(); - worker.init(gui); - testFrame.pack(); - testFrame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); - testFrame.setVisible(true); - new Thread(worker).start(); - - while(true) ; - } - - @Test - public void dummyTest() { - } - -// public static void main(String[] args) { -// new BKUGUITest().testBKUGUI(); -// } -} 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 deleted file mode 100644 index b01abe72..00000000 --- a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ /dev/null @@ -1,202 +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. - */ -/* - * 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 at.gv.egiz.stal.HashDataInput; -import at.gv.egiz.stal.impl.ByteArrayHashDataInput; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author clemens - */ -public class BKUGUIWorker implements Runnable { - - ActivationGUIFacade gui; - - public void init(ActivationGUIFacade gui) { - this.gui = gui; - } - - @Override - public void run() { - try { - - final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN", (byte)0x00, null); - - - 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, -1, signListener, "sign", cancelListener, "cancel", null, "hashdata"); - } - }; - HashDataInput signedRef1 = new ByteArrayHashDataInput( - "Ich bin ein einfacher Text mit Umlauten: öäüßéç@€\n123\n456\n\tHello, world!\n\nlkjsd\nnksdjf".getBytes(), - "ref-id-0000000000000000000000001", - "text/plain", - "UTF-8"); - - HashDataInput signedRef2 = new ByteArrayHashDataInput( - "HashDataInput_002".getBytes(), - "ref-id-000000002", - "application/xhtml+xml", - "UTF-8"); - - HashDataInput signedRef3 = new ByteArrayHashDataInput( - "HashDataInput_003".getBytes(), - "ref-id-000000003", - "application/xhtml+xml", - "UTF-8"); - - HashDataInput signedRef4 = new ByteArrayHashDataInput( - "HashDataInput_004".getBytes(), - "ref-id-000000004", - "text/xml", - "UTF-8"); - - // - List signedRefs = new ArrayList(); - signedRefs.add(signedRef1); - signedRefs.add(signedRef2); - signedRefs.add(signedRef3); - signedRefs.add(signedRef4); -// signedRefs.add(signedRef4); -// signedRefs.add(signedRef4); -// signedRefs.add(signedRef4); -// signedRefs.add(signedRef4); -// signedRefs = Collections.singletonList(signedRef1); - gui.showSecureViewer(signedRefs, returnListener, "return"); - } - }; - - - -// 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.showErrorDialog(BKUGUIFacade.ERR_NO_PCSC, null, null, null); - -// 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.showActivationProgressDialog(1, 3, null, null); - - gui.incrementProgress(); - - Thread.sleep(1000); - - gui.incrementProgress(); - - Thread.sleep(1000); - - gui.incrementProgress(); - - - Thread.sleep(1000); - - gui.showIdleDialog(null, 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(); - } - } -} diff --git a/BKUCommonGUI/pom.xml b/BKUCommonGUI/pom.xml index 393a5756..ef6e6692 100644 --- a/BKUCommonGUI/pom.xml +++ b/BKUCommonGUI/pom.xml @@ -7,7 +7,7 @@ 4.0.0 at.gv.egiz BKUCommonGUI - BKU Common GUI + BKU GUI 1.2.2-SNAPSHOT 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 de9a91b9..2663e8bf 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 @@ -132,7 +132,7 @@ public class BKUGUIImpl implements BKUGUIFacade { log.debug("scheduling gui initialization"); - SwingUtilities.invokeAndWait(new Runnable() { + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { diff --git a/BKUGuiExt/pom.xml b/BKUGuiExt/pom.xml new file mode 100644 index 00000000..87520232 --- /dev/null +++ b/BKUGuiExt/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + bku + at.gv.egiz + 1.2.2-SNAPSHOT + + at.gv.egiz + BKUGuiExt + 1.2.2-SNAPSHOT + BKU GUI Extension + + + at.gv.egiz + STALXService + 1.2.2-SNAPSHOT + + + at.gv.egiz + smccSTAL + 1.2.2-SNAPSHOT + + + + diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java new file mode 100644 index 00000000..c8927e1e --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUI.java @@ -0,0 +1,250 @@ +/* + * 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.*; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.event.ActionListener; +import java.net.URL; +import java.text.MessageFormat; +import java.util.Locale; +import java.util.ResourceBundle; +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JProgressBar; +import javax.swing.LayoutStyle; +import javax.swing.SwingUtilities; + +/** + * + * @author Clemens Orthacker + */ +public class ActivationGUI extends CardMgmtGUI implements ActivationGUIFacade { + + public static final String TITLE_ACTIVATION = "title.activation"; + public static final String LABEL_ACTIVATION = "label.activation"; + public static final String LABEL_ACTIVATION_STEP = "label.activation.step"; + public static final String LABEL_ACTIVATION_IDLE = "label.activation.idle"; + + public static final String HELP_ACTIVATION = "help.activation"; + + protected JProgressBar progressBar; + + public ActivationGUI(Container contentPane, + Locale locale, + Style guiStyle, + URL backgroundImgURL, + AbstractHelpListener helpListener) { + super(contentPane, locale, guiStyle, backgroundImgURL, helpListener); + + progressBar = new JProgressBar(); + } + + @Override + public void showActivationProgressDialog(final int currentStep, final int maxProgress, final ActionListener cancelListener, final String cancelCommand) { + + log.debug("scheduling activation progress dialog (step " + currentStep + ")"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("show activation progress dialog (step " + currentStep + ")"); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + mainPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + + JLabel infoLabel = new JLabel(); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + + if (renderHeaderPanel) { + titleLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); + infoLabel.setText(cardmgmtMessages.getString(LABEL_ACTIVATION)); + } else { + infoLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); + } + + helpListener.setHelpTopic(HELP_ACTIVATION); + + progressBar.setIndeterminate(false); + progressBar.setStringPainted(true); + progressBar.setString(null); //reset to percentage + progressBar.setMinimum(0); + progressBar.setMaximum(maxProgress); + + JLabel stepLabel = new JLabel(); + stepLabel.setFont(stepLabel.getFont().deriveFont(stepLabel.getFont().getStyle() & ~java.awt.Font.BOLD, stepLabel.getFont().getSize()-2)); + String stepPattern = cardmgmtMessages.getString(LABEL_ACTIVATION_STEP); + stepLabel.setText(MessageFormat.format(stepPattern, new Object[]{ currentStep })); + + 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) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(stepLabel) + .addComponent(progressBar))); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(infoVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(stepLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(progressBar))); + + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + 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(); + + } + }); + + } + + @Override + public void incrementProgress() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + progressBar.setValue(progressBar.getValue() + 1); + } + }); + + } + + @Override + public void showIdleDialog(final ActionListener cancelListener, final String cancelCommand) { + log.debug("scheduling idle dialog"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("show idle dialog"); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + mainPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + + JLabel infoLabel = new JLabel(); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + + if (renderHeaderPanel) { + titleLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); + infoLabel.setText(cardmgmtMessages.getString(LABEL_ACTIVATION)); + } else { + infoLabel.setText(cardmgmtMessages.getString(TITLE_ACTIVATION)); + } + + helpListener.setHelpTopic(HELP_ACTIVATION); + + progressBar.setIndeterminate(true); + progressBar.setStringPainted(true); + progressBar.setString(""); //not string painted progressbar is smaller + + JLabel stepLabel = new JLabel(); + stepLabel.setFont(stepLabel.getFont().deriveFont(stepLabel.getFont().getStyle() & ~java.awt.Font.BOLD, stepLabel.getFont().getSize()-2)); + stepLabel.setText(cardmgmtMessages.getString(LABEL_ACTIVATION_IDLE)); + + 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) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(stepLabel) + .addComponent(progressBar))); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(infoVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(stepLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(progressBar))); + + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + 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(); + + } + }); + + } +} diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.java new file mode 100644 index 00000000..3fc14d04 --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/ActivationGUIFacade.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.bku.gui; + +import at.gv.egiz.bku.gui.*; +import java.awt.event.ActionListener; + +/** + * + * @author Clemens Orthacker + */ +public interface ActivationGUIFacade extends BKUGUIFacade { + + public void showActivationProgressDialog(int currentStep, int maxProgress, ActionListener cancelListener, String cancelCommand); + + public void incrementProgress(); + + public void showIdleDialog(ActionListener cancelListener, String cancelCommand); + +} diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.java new file mode 100644 index 00000000..c8e1826c --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/CardMgmtGUI.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.bku.gui.*; +import java.awt.Container; +import java.net.URL; +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * Common superclass for Activation and PinManagement GUIs + * + * @author Clemens Orthacker + */ +public class CardMgmtGUI extends BKUGUIImpl { + + public static final String CARDMGMT_MESSAGES_BUNDLE = "at/gv/egiz/bku/gui/ActivationMessages"; + + protected ResourceBundle cardmgmtMessages; + + public CardMgmtGUI(Container contentPane, + Locale locale, + Style guiStyle, + URL backgroundImgURL, + AbstractHelpListener helpListener) { + super(contentPane, locale, guiStyle, backgroundImgURL, helpListener); + + } + + @Override + protected void loadMessageBundle(Locale locale) { + super.loadMessageBundle(locale); + + if (locale != null) { + Locale lang = new Locale(locale.getLanguage().substring(0,2)); + log.debug("loading applet resources for language: " + lang.toString()); + cardmgmtMessages = ResourceBundle.getBundle(CARDMGMT_MESSAGES_BUNDLE, lang); + } else { + cardmgmtMessages = ResourceBundle.getBundle(CARDMGMT_MESSAGES_BUNDLE); + } + } + + @Override + protected String getMessage(String key) { + if (super.hasMessage(key)) { + return super.getMessage(key); + } + return cardmgmtMessages.getString(key); + } + + @Override + protected boolean hasMessage(String key) { + return (cardmgmtMessages.containsKey(key) || super.hasMessage(key)); + } +} 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 new file mode 100644 index 00000000..3d503510 --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -0,0 +1,670 @@ +/* + * 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.*; +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; +import java.awt.event.MouseMotionAdapter; +import java.net.URL; +import java.text.MessageFormat; +import java.util.Locale; +import java.util.Map; +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +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 org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * TODO pull out ResourceBundle to common superclass for activationGUI and pinMgmtGUI + * @author Clemens Orthacker + */ +public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFacade { + + protected static final Log log = LogFactory.getLog(PINManagementGUI.class); + + /** remember the pinfield to return to worker */ + protected JPasswordField oldPinField; + /** remember the pinSpec to return to worker */ + protected PINSpec pinSpec; + + public PINManagementGUI(Container contentPane, + Locale locale, + Style guiStyle, + URL backgroundImgURL, + AbstractHelpListener helpListener) { + super(contentPane, locale, guiStyle, backgroundImgURL, helpListener); + } + + @Override + public char[] getOldPin() { + if (oldPinField != null) { + char[] pin = oldPinField.getPassword(); + oldPinField = null; + return pin; + } + return null; + } + + @Override + public PINSpec getSelectedPINSpec() { + return pinSpec; + } + + @Override + public void showPINManagementDialog(final Map pins, + final ActionListener activateListener, + final String activateCmd, + final String changeCmd, + final String unblockCmd, + final String verifyCmd, + final ActionListener cancelListener, + final String cancelCmd) { + + log.debug("scheduling PIN managment dialog"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + log.debug("show PIN management dialog"); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + helpListener.setHelpTopic(HELP_PINMGMT); + + JLabel mgmtLabel = new JLabel(); + mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + + if (renderHeaderPanel) { + titleLabel.setText(getMessage(TITLE_PINMGMT)); + String infoPattern = getMessage(MESSAGE_PINMGMT); + mgmtLabel.setText(MessageFormat.format(infoPattern, pins.size())); + } else { + mgmtLabel.setText(getMessage(TITLE_PINMGMT)); + } + + final PINStatusTableModel tableModel = new PINStatusTableModel(pins); + final JTable pinStatusTable = new JTable(tableModel); + pinStatusTable.setDefaultRenderer(PINSpec.class, new PINSpecRenderer()); + pinStatusTable.setDefaultRenderer(STATUS.class, new PINStatusRenderer(cardmgmtMessages)); + pinStatusTable.setTableHeader(null); + 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)); + activateButton.addActionListener(activateListener); + + pinStatusTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + pinStatusTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(final ListSelectionEvent e) { + //invoke later to allow thread to paint selection background + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + ListSelectionModel lsm = (ListSelectionModel) e.getSource(); + int selectionIdx = lsm.getMinSelectionIndex(); + if (selectionIdx >= 0) { + pinSpec = (PINSpec) tableModel.getValueAt(selectionIdx, 0); + STATUS status = (STATUS) tableModel.getValueAt(selectionIdx, 1); + + if (status == STATUS.NOT_ACTIV) { + activateButton.setText(getMessage(BUTTON_ACTIVATE)); + activateButton.setEnabled(true); + activateButton.setActionCommand(activateCmd); + } else if (status == STATUS.BLOCKED) { + activateButton.setText(getMessage(BUTTON_UNBLOCK)); + activateButton.setEnabled(true); + activateButton.setActionCommand(unblockCmd); + } else if (status == STATUS.ACTIV) { + activateButton.setText(getMessage(BUTTON_CHANGE)); + activateButton.setEnabled(true); + activateButton.setActionCommand(changeCmd); + } else if (status == STATUS.UNKNOWN) { + activateButton.setText(getMessage(BUTTON_VERIFY)); + activateButton.setEnabled(true); + activateButton.setActionCommand(verifyCmd); + } + } + } + }); + } + }); + + //select first entry + pinStatusTable.getSelectionModel().setSelectionInterval(0, 0); + + JScrollPane pinStatusScrollPane = new JScrollPane(pinStatusTable); + + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(mgmtLabel); + GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(mgmtLabel); + if (!renderHeaderPanel) { + messageHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + messageVertical + .addComponent(helpLabel); + } + + mainPanelLayout.setHorizontalGroup( + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(messageHorizontal) + .addComponent(pinStatusScrollPane, 0, 0, Short.MAX_VALUE)); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(messageVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinStatusScrollPane, 0, 0, pinStatusTable.getPreferredSize().height+3)); + + JButton cancelButton = new JButton(); + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + cancelButton.setText(getMessage(BUTTON_CLOSE)); + cancelButton.setActionCommand(cancelCmd); + cancelButton.addActionListener(cancelListener); + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(activateButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + + GroupLayout.Group buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(activateButton) + .addComponent(cancelButton); + + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); + buttonPanelLayout.setVerticalGroup(buttonVertical); + + contentPanel.validate(); + } + }); + } + + @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) { + String title, msg; + Object[] params; + if (retries < 0) { + params = new Object[2]; + if (shortText) { + params[0] = "PIN"; + } else { + params[0] = pinSpec.getLocalizedName(); + } + params[1] = pinSpec.getLocalizedLength(); + 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, MESSAGE_MGMT_PARAM, PINSIZE; + HELP_TOPIC = HELP_PINMGMT; + + PINSIZE = (pinSpec.getMaxLength() > pinSpec.getMinLength()) ? + pinSpec.getMinLength() + "-" + pinSpec.getMaxLength() : + String.valueOf(pinSpec.getMinLength()); + + 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; + PINSIZE = pinSpec.getLocalizedLength(); + } 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 retry pin dialog"); + TITLE = TITLE_RETRY; + MESSAGE_MGMT = (retries < 2) ? + MESSAGE_LAST_RETRY : MESSAGE_RETRIES; + MESSAGE_MGMT_PARAM = String.valueOf(retries); + } + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + helpListener.setHelpTopic(HELP_TOPIC); + + JLabel mgmtLabel = new JLabel(); + 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); + mgmtLabel.setText(MessageFormat.format(mgmtPattern, MESSAGE_MGMT_PARAM)); + } else { + mgmtLabel.setText(getMessage(TITLE)); + } + + //////////////////////////////////////////////////////////////// + // 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_VERIFYPIN_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(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() & ~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.setActionCommand(okCommand); + pinField.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(); + } + } + } + }); + + 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 (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(); + } + } + }); + + 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)); + } + + JLabel pinsizeLabel = new JLabel(); + pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~Font.BOLD, pinsizeLabel.getFont().getSize()-2)); + String pinsizePattern = getMessage(LABEL_PINSIZE); + pinsizeLabel.setText(MessageFormat.format(pinsizePattern, new Object[]{PINSIZE})); + + //////////////////////////////////////////////////////////////// + // NON-PINPAD SPECIFIC LAYOUT SECTION + //////////////////////////////////////////////////////////////// + + pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + 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 (type == DIALOG.CHANGE) { + pinHorizontal + .addGroup(mainPanelLayout.createSequentialGroup() + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(oldPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); + + pinVertical + .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 if (type == DIALOG.ACTIVATE) { + pinHorizontal + .addGroup(mainPanelLayout.createSequentialGroup() + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); + + pinVertical + .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 { // 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); + + 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) + .addGroup(infoHorizontal) + .addGroup(pinHorizontal)); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(infoVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pinVertical)); + + contentPanel.validate(); + + } + }); + } + + @Override + protected int initButtonSize() { + int bs = super.initButtonSize(); + + JButton b = new JButton(); + b.setText(getMessage(BUTTON_ACTIVATE)); + if (b.getPreferredSize().width > bs) { + bs = b.getPreferredSize().width; + } + b.setText(getMessage(BUTTON_CHANGE)); + if (b.getPreferredSize().width > bs) { + bs = b.getPreferredSize().width; + } + b.setText(getMessage(BUTTON_UNBLOCK)); + if (b.getPreferredSize().width > bs) { + bs = b.getPreferredSize().width; + } + b.setText(getMessage(BUTTON_CANCEL)); + if (b.getPreferredSize().width > bs) { + bs = b.getPreferredSize().width; + } + + return bs; + } + +} 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 new file mode 100644 index 00000000..297173d9 --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -0,0 +1,118 @@ +/* + * 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.*; +import at.gv.egiz.smcc.PINSpec; +import java.awt.event.ActionListener; +import java.util.Map; + +/** + * + * @author Clemens Orthacker + */ +public interface PINManagementGUIFacade extends BKUGUIFacade { + + public static final String HELP_PINMGMT = "help.pin.mgmt"; +// public static final String HELP_VERIFY_PIN = "help.pin.verify"; + 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"; + + // 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_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"; + + 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 ERR_PIN_FORMAT = "err.pin.format"; + public static final String ERR_PIN_CONFIRMATION = "err.pin.confirmation"; + public static final String ERR_PIN_OPERATION_ABORTED = "err.pin.operation.aborted"; + public static final String ERR_UNSUPPORTED_CARD = "err.unsupported.card"; + + 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"; + public static final String STATUS_NOT_ACTIVE = "status.not.active"; + 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 showPINDialog(DIALOG type, PINSpec pin, + 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); + + 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(); + + public PINSpec getSelectedPINSpec(); +} diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java new file mode 100644 index 00000000..e3d73e1f --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.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.bku.gui; + +import at.gv.egiz.smcc.PINSpec; +import javax.swing.table.DefaultTableCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public class PINSpecRenderer extends DefaultTableCellRenderer { + + private static final Log log = LogFactory.getLog(PINSpecRenderer.class); + + @Override + protected void setValue(Object value) { + PINSpec pinSpec = (PINSpec) value; + super.setText(pinSpec.getLocalizedName()); + } + +} diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java new file mode 100644 index 00000000..83ff74f2 --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java @@ -0,0 +1,61 @@ +/* + * 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.PINManagementGUIFacade.STATUS; +import java.awt.Color; +import java.awt.Font; +import java.util.ResourceBundle; +import javax.swing.table.DefaultTableCellRenderer; + +/** + * + * @author Clemens Orthacker + */ +public class PINStatusRenderer extends DefaultTableCellRenderer { + +// private static final Log log = LogFactory.getLog(PINStatusRenderer.class); + + public static final Color RED = new Color(0.9f, 0.0f, 0.0f); + public static final Color GREEN = new Color(0.0f, 0.8f, 0.0f); + protected ResourceBundle messages; + + public PINStatusRenderer(ResourceBundle messages) { + this.messages = messages; + } + + @Override + protected void setValue(Object value) { + STATUS pinStatus = (STATUS) value; + super.setFont(super.getFont().deriveFont(super.getFont().getStyle() | Font.BOLD)); + + if (pinStatus == STATUS.NOT_ACTIV) { + super.setForeground(RED); + super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_NOT_ACTIVE) + ""); + } else if (pinStatus == STATUS.ACTIV) { + super.setForeground(GREEN); + super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_ACTIVE) + ""); + } else if (pinStatus == STATUS.BLOCKED) { + super.setForeground(RED); + super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_BLOCKED) + ""); + } else { + super.setForeground(Color.BLACK); + super.setText("" + messages.getString(PINManagementGUIFacade.STATUS_UNKNOWN) + ""); + } + } +} diff --git a/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java new file mode 100644 index 00000000..052c13b2 --- /dev/null +++ b/BKUGuiExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.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.gui; + +import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; +import at.gv.egiz.smcc.PINSpec; +import java.util.Map; +import javax.swing.table.DefaultTableModel; + +/** + * + * @author Clemens Orthacker + */ +public class PINStatusTableModel extends DefaultTableModel { + +// protected static final Log log = LogFactory.getLog(PINStatusTableModel.class); + protected Class[] types; + + public PINStatusTableModel(Map pinStatuses) { + super(0, 2); + if (pinStatuses == null) { + throw new RuntimeException("pinStatuses must not be null"); + } +// log.trace(pinStatuses.size() + " PINs"); + types = new Class[] { PINSpec.class, STATUS.class }; + for (PINSpec pinSpec : pinStatuses.keySet()) { + addRow(new Object[] { pinSpec, pinStatuses.get(pinSpec) }); + } +// PINSpec activePIN = new PINSpec(0, 1, null, "active-PIN", (byte) 0x01); +// PINSpec blockedPIN = new PINSpec(0, 1, null, "blocked-PIN", (byte) 0x01); +// addRow(new Object[] { activePIN, PINStatusProvider.STATUS.ACTIV }); +// addRow(new Object[] { blockedPIN, PINStatusProvider.STATUS.BLOCKED }); + } + + @Override + public Class getColumnClass(int columnIndex) { + return types[columnIndex]; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return false; + } +} 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 new file mode 100644 index 00000000..977d6e3a --- /dev/null +++ b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -0,0 +1,69 @@ +# 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. + +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.success=Erfolg +title.change.success=Erfolg + +# removed message.* prefix to reuse keys as help keys +pin.mgmt=Die Karte verf\u00FCgt \u00FCber {0} PINs +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. + +label.activation=e-card Aktivierungsprozess +label.activation.step=Schritt {0} +label.activation.idle=Warte auf Server... +label.old.pin=Alte {0}: +label.new.pin=Neue {0}: +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=Falsche {0}, noch {1} Versuche +err.locked={0} gesperrt. +err.not.active={0} nicht aktiviert. +err.pin.format=Ung\u00FCltige {0} L\u00E4nge, verlangt sind {1} Stellen. +err.pin.confirmation={0} und Best\u00E4tigung stimmen nicht \u00FCberein. +err.pin.operation.aborted=Der Vorgang f\u00FCr {0} wurde abgebrochen. +err.unsupported.card=Die Karte wird nicht unterst\u00FCtzt + +status.not.active=NICHT AKTIV +status.active=AKTIV +status.blocked=GESPERRT +status.unknown=UNBEKANNT 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 new file mode 100644 index 00000000..7f01971b --- /dev/null +++ b/BKUGuiExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -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. + +title.activation=Activation +title.pin.mgmt=PIN Management +title.activate.pin=Activate PIN +title.verify.pin=Enter PIN +title.change.pin=Change PIN +title.unblock.pin=Unblock PIN +title.activate.success=Success +title.change.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). +activate.success={0} successfully activated +change.success={0} successfully changed + +label.activation=e-card activation process +label.activation.step=Step {0} +label.activation.idle=Wait for server... +label.old.pin=Old {0}: +label.new.pin=New {0}: +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. +err.pin.format=Invalid {0} length, {1} digit(s) required. +err.pin.confirmation={0} and confirmation do not match. +err.pin.operation.aborted=The operation on {0} was aborted. +err.unsupported.card=This card is not supported + +status.not.active=NOT ACTIVE +status.active=ACTIVE +status.blocked=BLOCKED +status.unknown=UNKNOWN diff --git a/BKUGuiExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java b/BKUGuiExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java new file mode 100644 index 00000000..49ae577b --- /dev/null +++ b/BKUGuiExt/src/test/java/at/gv/egiz/bku/gui/ActivationGuiTest.java @@ -0,0 +1,63 @@ +/* +* 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. + */ + +package at.gv.egiz.bku.gui; + +import at.gv.egiz.bku.gui.*; +import java.awt.Container; +import java.awt.Dimension; +import javax.swing.JFrame; +import org.junit.Ignore; +import org.junit.Test; + + +/** + * + * @author clemens + */ +@Ignore +public class ActivationGuiTest { + + @Test + public void testBKUGUI() { + JFrame testFrame = new JFrame("BKUGUITest"); + Container contentPane = testFrame.getContentPane(); + contentPane.setPreferredSize(new Dimension(152, 145)); +// contentPane.setPreferredSize(new Dimension(300, 190)); + ActivationGUIFacade gui = new ActivationGUI(contentPane, null, BKUGUIFacade.Style.tiny, null, null); + BKUGUIWorker worker = new BKUGUIWorker(); + worker.init(gui); + testFrame.pack(); + testFrame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + testFrame.setVisible(true); + new Thread(worker).start(); + + while(true) ; + } + + @Test + public void dummyTest() { + } + +// public static void main(String[] args) { +// new BKUGUITest().testBKUGUI(); +// } +} diff --git a/BKUGuiExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUGuiExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java new file mode 100644 index 00000000..74ea8952 --- /dev/null +++ b/BKUGuiExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -0,0 +1,203 @@ +/* + * 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. + */ +package at.gv.egiz.bku.gui; + +import at.gv.egiz.bku.gui.*; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author clemens + */ +public class BKUGUIWorker implements Runnable { + + ActivationGUIFacade gui; + + public void init(ActivationGUIFacade gui) { + this.gui = gui; + } + + @Override + public void run() { + try { + + final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN", (byte)0x00, null); + + + 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, -1, signListener, "sign", cancelListener, "cancel", null, "hashdata"); + } + }; + HashDataInput signedRef1 = new ByteArrayHashDataInput( + "Ich bin ein einfacher Text mit Umlauten: öäüßéç@€\n123\n456\n\tHello, world!\n\nlkjsd\nnksdjf".getBytes(), + "ref-id-0000000000000000000000001", + "text/plain", + "UTF-8"); + + HashDataInput signedRef2 = new ByteArrayHashDataInput( + "HashDataInput_002".getBytes(), + "ref-id-000000002", + "application/xhtml+xml", + "UTF-8"); + + HashDataInput signedRef3 = new ByteArrayHashDataInput( + "HashDataInput_003".getBytes(), + "ref-id-000000003", + "application/xhtml+xml", + "UTF-8"); + + HashDataInput signedRef4 = new ByteArrayHashDataInput( + "HashDataInput_004".getBytes(), + "ref-id-000000004", + "text/xml", + "UTF-8"); + + // + List signedRefs = new ArrayList(); + signedRefs.add(signedRef1); + signedRefs.add(signedRef2); + signedRefs.add(signedRef3); + signedRefs.add(signedRef4); +// signedRefs.add(signedRef4); +// signedRefs.add(signedRef4); +// signedRefs.add(signedRef4); +// signedRefs.add(signedRef4); +// signedRefs = Collections.singletonList(signedRef1); + gui.showSecureViewer(signedRefs, returnListener, "return"); + } + }; + + + +// 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.showErrorDialog(BKUGUIFacade.ERR_NO_PCSC, null, null, null); + +// 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.showActivationProgressDialog(1, 3, null, null); + + gui.incrementProgress(); + + Thread.sleep(1000); + + gui.incrementProgress(); + + Thread.sleep(1000); + + gui.incrementProgress(); + + + Thread.sleep(1000); + + gui.showIdleDialog(null, 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(); + } + } +} diff --git a/BKULocal/pom.xml b/BKULocal/pom.xml index 9704b7db..81cb3df8 100644 --- a/BKULocal/pom.xml +++ b/BKULocal/pom.xml @@ -93,6 +93,21 @@ smccSTAL 1.2.2-SNAPSHOT + + at.gv.egiz + BKUGuiExt + 1.2.2-SNAPSHOT + + + at.gv.egiz + smccSTALExt + 1.2.2-SNAPSHOT + + + at.gv.egiz + BKUViewer + 1.2.2-SNAPSHOT + BKUHelp at.gv.egiz @@ -117,16 +132,6 @@ commons-logging commons-logging - - at.gv.egiz - BKUApplet - 1.2.2-SNAPSHOT - - - at.gv.egiz - BKUViewer - 1.2.2-SNAPSHOT - diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/gui/GUIProxy.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/gui/GUIProxy.java new file mode 100644 index 00000000..38dd04d9 --- /dev/null +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/gui/GUIProxy.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.local.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import javax.swing.JFrame; + +/** + * + * @author Clemens Orthacker + */ +public class GUIProxy implements InvocationHandler { + + JFrame frame; + BKUGUIFacade delegate; + + static public Object newInstance(BKUGUIFacade gui, JFrame frame, Class[] interfaces) { + return java.lang.reflect.Proxy.newProxyInstance(gui.getClass().getClassLoader(), + interfaces, + new GUIProxy(gui, frame)); + } + + private GUIProxy(BKUGUIFacade delegate, JFrame frame) { + this.frame = frame; + this.delegate = delegate; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + + if (method.getName().startsWith("show")) { + frame.setVisible(true); + frame.toFront(); + return method.invoke(delegate, args); + } else { //if (method.getName().startsWith("get")) { + return method.invoke(delegate, args); + } + } +} 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 deleted file mode 100644 index c724c071..00000000 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java +++ /dev/null @@ -1,156 +0,0 @@ -package at.gv.egiz.bku.local.stal; - -import java.awt.event.ActionListener; -import java.util.List; - -import java.util.Locale; -import javax.swing.JDialog; - -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.stal.HashDataInput; -import javax.swing.JFrame; - -public class BKUGuiProxy implements BKUGUIFacade { - - private BKUGUIFacade delegate; - private JFrame dialog; - - public BKUGuiProxy(JFrame dialog, BKUGUIFacade delegate) { - this.delegate = delegate; - this.dialog = dialog; - } - - private void showDialog() { - dialog.setVisible(true); - dialog.setAlwaysOnTop(true); - } - - @Override - public char[] getPin() { - return delegate.getPin(); - } - -// @Override -// public void init(Container contentPane, Locale locale, URL bgImage, ActionListener helpListener) { -// delegate.init(contentPane, locale, bgImage, helpListener); -// } - - @Override - public Locale getLocale() { - 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 showCardPINDialog(PINSpec pinSpec, int numRetries, - ActionListener okListener, String okCommand, - ActionListener cancelListener, String cancelCommand) { - showDialog(); - delegate.showCardPINDialog(pinSpec, numRetries, okListener, okCommand, - cancelListener, cancelCommand); - } - - @Override - public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, - String actionCommand) { - showDialog(); - delegate.showErrorDialog(errorMsgKey, errorMsgParams, okListener, actionCommand); - } - - @Override - public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams) { - showDialog(); - 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 showSignaturePINDialog(PINSpec pinSpec, int numRetries, - ActionListener okListener, String okCommand, - ActionListener cancelListener, String cancelCommand, - ActionListener hashdataListener, String hashdataCommand) { - showDialog(); - 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 showSecureViewer(List signedReferences, - ActionListener okListener, - String okCommand) { - showDialog(); - delegate.showSecureViewer(signedReferences, okListener, okCommand); - } - - @Override - public void showMessageDialog(String titleKey, - String msgKey, Object[] msgParams, - String buttonKey, ActionListener okListener, String okCommand) { - showDialog(); - delegate.showMessageDialog(titleKey, msgKey, msgParams, buttonKey, okListener, okCommand); - } - - @Override - public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams) { - showDialog(); - delegate.showMessageDialog(titleKey, msgKey, msgParams); - } - - @Override - public void showMessageDialog(String titleKey, String msgKey) { - 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 ca4d35d1..75f71be6 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 @@ -18,11 +18,13 @@ package at.gv.egiz.bku.local.stal; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.smccstal.AbstractBKUWorker; +import at.gv.egiz.bku.smccstal.PINManagementRequestHandler; 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.PINManagementRequest; import java.util.List; import javax.swing.JFrame; @@ -39,16 +41,18 @@ public class LocalBKUWorker extends AbstractBKUWorker { this.container = container; addRequestHandler(SignRequest.class, new LocalSignRequestHandler(new LocalSecureViewer(gui))); + addRequestHandler(PINManagementRequest.class, new PINManagementRequestHandler()); } + /** does not change container's visibility (use quit request to close) */ @Override public List handleRequest(List requestList) { signatureCard = null; List responses = super.handleRequest(requestList); - // container.setVisible(false); return responses; } + /** overrides handle quit from abstract bku worker, make container invisible */ @Override public STALResponse handleRequest(STALRequest request) { if (request instanceof QuitRequest) { diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSTALFactory.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSTALFactory.java index 4c9554e2..712fb969 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSTALFactory.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSTALFactory.java @@ -24,6 +24,9 @@ import java.util.Locale; import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.BKUGUIImpl; +import at.gv.egiz.bku.gui.PINManagementGUI; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.local.gui.GUIProxy; import at.gv.egiz.bku.local.gui.LocalHelpListener; import at.gv.egiz.stal.STAL; import at.gv.egiz.stal.STALFactory; @@ -33,10 +36,16 @@ import javax.swing.JRootPane; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +/** + * Creates a PINManagementGUI and a LocalBKUWorker, which in turn registers + * PINManagementRequestHandler from smccSTALExt. + * The RequestHandler expects PINManagementGUIFacade, therefore BKUGUIProxy has to implement the extended GUI. + * @author clemens + */ public class LocalSTALFactory implements STALFactory { protected static final Log log = LogFactory.getLog(LocalSTALFactory.class); - protected static final Dimension PREFERRED_SIZE = new Dimension(300, 189); + protected static final Dimension PREFERRED_SIZE = new Dimension(318, 200); protected String helpURL; protected Locale locale; @@ -47,7 +56,7 @@ public class LocalSTALFactory implements STALFactory { //http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html // use undecorated JFrame instead of JWindow, // which creates an invisible owning frame and therefore cannot getFocusInWindow() - JFrame dialog = new JFrame(); + JFrame dialog = new JFrame("Bürgerkarte"); dialog.setUndecorated(true); dialog.getRootPane().setWindowDecorationStyle(JRootPane.NONE); @@ -64,12 +73,13 @@ public class LocalSTALFactory implements STALFactory { } catch (MalformedURLException ex) { log.error("failed to configure help listener: " + ex.getMessage(), ex); } - BKUGUIFacade gui = new BKUGUIImpl(dialog.getContentPane(), + PINManagementGUIFacade gui = new PINManagementGUI(dialog.getContentPane(), dialog.getLocale(), BKUGUIFacade.Style.advanced, null, helpListener); - stal = new LocalBKUWorker(new BKUGuiProxy(dialog, gui), dialog); + BKUGUIFacade proxy = (BKUGUIFacade) GUIProxy.newInstance(gui, dialog, new Class[] { PINManagementGUIFacade.class} ); + stal = new LocalBKUWorker(proxy, dialog); dialog.setPreferredSize(PREFERRED_SIZE); dialog.pack(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/webapp/PINManagementServlet.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/webapp/PINManagementServlet.java new file mode 100644 index 00000000..89e526ac --- /dev/null +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/webapp/PINManagementServlet.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.local.webapp; + +import at.gv.egiz.bku.local.stal.LocalSTALFactory; +import at.gv.egiz.marshal.MarshallerFactory; +import at.gv.egiz.stal.QuitRequest; +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; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import org.apache.regexp.REUtil; + +/** + * PINManagementBKUWorker for non-applet version + * @author Clemens Orthacker + */ +public class PINManagementServlet extends HttpServlet { + +// static JAXBContext stalCtx; + + /** + * Processes requests for both HTTP GET and POST methods. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + protected void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + LocalSTALFactory sf = new LocalSTALFactory(); + + ArrayList stalReqs = new ArrayList(); + stalReqs.add(new PINManagementRequest()); + stalReqs.add(new QuitRequest()); + + List stalResps = sf.createSTAL().handleRequest(stalReqs); + + String redirect = request.getParameter("redirect"); + if (redirect != null) { + String referer = request.getHeader("Referer"); + if (referer != null) { + redirect = new URL(new URL(referer), redirect).toExternalForm(); + } + response.sendRedirect(redirect); + } else { + response.setStatus(HttpServletResponse.SC_OK); +// if (stalResps.get(0) != null) { +// PrintWriter out = response.getWriter(); +// try { +// response.setContentType("text/xml;charset=UTF-8"); +// // cannot directly marshal STALResponse, no ObjectFactory in at.gv.egiz.stal +// if (stalCtx == null) { +// stalCtx = JAXBContext.newInstance("at.gv.egiz.stal:at.gv.egiz.stal.ext"); +// } +// Marshaller m = MarshallerFactory.createMarshaller(stalCtx); +// m.marshal(stalResps.get(0), out); +// out.close(); +// } catch (JAXBException ex) { +// throw new ServletException("Failed to marshal STAL response", ex); +// } finally { +// out.close(); +// } +// } else { +// throw new ServletException("internal error"); +// } + } + + +// try { +// out.println(""); +// out.println(""); +// out.println("Servlet PINManagementServlet"); +// out.println(""); +// out.println(""); +// out.println("

Servlet PINManagementServlet at " + request.getContextPath() + "

"); +// out.println("

" + stalResps.size() + " responses:

    "); +// for (STALResponse resp : stalResps) { +// out.println("
  • " + resp.getClass()); +// } +// Enumeration headers = request.getHeaderNames(); +// out.println("

headers:

    "); +// while (headers.hasMoreElements()) { +// String header = headers.nextElement(); +// out.println("
  • " + header + ": " + request.getHeader(header)); +// } +// Enumeration params = request.getParameterNames(); +// out.println("

params:

    "); +// while (params.hasMoreElements()) { +// String param = params.nextElement(); +// out.println("
  • " + param + ": " + request.getParameter(param)); +// } +// out.println("

"); +// out.println(""); +// } finally { +// out.close(); +// } + } + + // + /** + * Handles the HTTP GET method. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Handles the HTTP POST method. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Returns a short description of the servlet. + * @return a String containing servlet description + */ + @Override + public String getServletInfo() { + return "Short description"; + }// +} diff --git a/BKULocal/src/main/webapp/WEB-INF/web.xml b/BKULocal/src/main/webapp/WEB-INF/web.xml index 8e696570..83f33d9e 100644 --- a/BKULocal/src/main/webapp/WEB-INF/web.xml +++ b/BKULocal/src/main/webapp/WEB-INF/web.xml @@ -40,6 +40,10 @@ help /help.jsp + + PINManagementServlet + at.gv.egiz.bku.local.webapp.PINManagementServlet + BKUServlet /http-security-layer-request @@ -53,7 +57,11 @@ /help/* - + + + 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