summaryrefslogtreecommitdiff
path: root/smccSTAL/src
diff options
context:
space:
mode:
Diffstat (limited to 'smccSTAL/src')
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java60
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java136
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java105
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java76
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java72
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java206
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java86
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java192
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java85
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java46
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java141
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java33
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java21
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java43
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java136
-rw-r--r--smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/StatusRequestHandler.java72
-rw-r--r--smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java105
-rw-r--r--smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java126
-rw-r--r--smccSTAL/src/test/resources/log4j.properties19
19 files changed, 1760 insertions, 0 deletions
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java
new file mode 100644
index 00000000..00738188
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/AbstractPINProvider.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.pin.gui;
+
+import at.gv.egiz.smcc.pin.gui.PINProvider;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * common super class providing action listener for all PIN GUIs
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public abstract class AbstractPINProvider implements ActionListener {
+
+ protected static final Log log = LogFactory.getLog(AbstractPINProvider.class);
+
+ protected String action;
+ protected boolean actionPerformed;
+
+ protected synchronized void waitForAction() throws InterruptedException {
+ try {
+ while (!actionPerformed) {
+ this.wait();
+ }
+ } catch (InterruptedException e) {
+ log.error("[" + Thread.currentThread().getName() + "] interrupt in waitForAction");
+ throw e;
+ }
+ actionPerformed = false;
+ }
+
+ private synchronized void actionPerformed() {
+ actionPerformed = true;
+ notify();//All();
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.debug("[" + Thread.currentThread().getName() + "] action performed - " + e.getActionCommand());
+ action = e.getActionCommand();
+ actionPerformed();
+ }
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java
new file mode 100644
index 00000000..81db0e90
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.pin.gui;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.bku.smccstal.SecureViewer;
+import at.gv.egiz.smcc.CancelledException;
+import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.pin.gui.PINGUI;
+import at.gv.egiz.stal.signedinfo.SignedInfoType;
+import java.security.DigestException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The number of retries is not fixed and there is no way (?) to obtain this value.
+ * A PINProvider should therefore maintain an internal retry counter or flag
+ * to decide whether or not to warn the user (num retries passed in providePIN).
+ *
+ * Therefore PINProvider objects should not be reused.
+ *
+ * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated)
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class SignPINGUI extends SignPINProvider implements PINGUI {
+
+ protected static final Log log = LogFactory.getLog(SignPINGUI.class);
+
+ private boolean retry = false;
+
+ public SignPINGUI(BKUGUIFacade gui, SecureViewer viewer, SignedInfoType signedInfo) {
+ super(gui, viewer, signedInfo);
+ }
+
+ @Override
+ public void enterPINDirect(PINSpec spec, int retries)
+ throws CancelledException, InterruptedException {
+ if (retry) {
+ gui.showEnterPINDirect(spec, retries);
+ } else {
+ showSignatureData(spec);
+ gui.showEnterPINDirect(spec, -1);
+ retry = true;
+ }
+ }
+
+ @Override
+ public void enterPIN(PINSpec spec, int retries)
+ throws CancelledException, InterruptedException {
+ if (retry) {
+ gui.showEnterPIN(spec, retries);
+ } else {
+ showSignatureData(spec);
+ gui.showEnterPIN(spec, -1);
+ retry = true;
+ }
+ }
+
+ private void showSignatureData(PINSpec spec)
+ throws CancelledException, InterruptedException {
+
+ gui.showSignatureDataDialog(spec,
+ this, "enterPIN",
+ this, "cancel",
+ this, "secureViewer");
+
+ do {
+ log.trace("[" + Thread.currentThread().getName() + "] wait for action");
+ waitForAction();
+ log.trace("[" + Thread.currentThread().getName() + "] received action " + action);
+
+ if ("secureViewer".equals(action)) {
+ try {
+ viewer.displayDataToBeSigned(signedInfo, this, "signatureData");
+ } catch (DigestException ex) {
+ log.error("Bad digest value: " + ex.getMessage());
+ gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH,
+ new Object[]{ex.getMessage()},
+ this, "error");
+ } catch (Exception ex) {
+ log.error("Could not display hashdata inputs: " +
+ ex.getMessage());
+ gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA,
+ new Object[]{ex.getMessage()},
+ this, "error");
+ }
+ } else if ("signatureData".equals(action)) {
+ gui.showSignatureDataDialog(spec,
+ this, "enterPIN",
+ this, "cancel",
+ this, "secureViewer");
+ } else if ("enterPIN".equals(action)) {
+ return;
+ } else if ("cancel".equals(action) ||
+ "error".equals(action)) {
+ gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT,
+ BKUGUIFacade.MESSAGE_WAIT);
+ throw new CancelledException(spec.getLocalizedName() +
+ " entry cancelled");
+ } else {
+ log.error("unknown action command " + action);
+ }
+ } while (true);
+ }
+
+ @Override
+ public void validKeyPressed() {
+ gui.validKeyPressed();
+ }
+
+ @Override
+ public void correctionButtonPressed() {
+ gui.correctionButtonPressed();
+ }
+
+ @Override
+ public void allKeysCleared() {
+ gui.allKeysCleared();
+ }
+
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java
new file mode 100644
index 00000000..fc1d39af
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.pin.gui;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.bku.smccstal.SecureViewer;
+import at.gv.egiz.smcc.CancelledException;
+import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.pin.gui.PINProvider;
+import at.gv.egiz.stal.signedinfo.SignedInfoType;
+import java.security.DigestException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The number of retries is not fixed and there is no way (?) to obtain this value.
+ * A PINProvider should therefore maintain an internal retry counter or flag
+ * to decide whether or not to warn the user (num retries passed in providePIN).
+ *
+ * Therefore PINProvider objects should not be reused.
+ *
+ * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated)
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class SignPINProvider extends AbstractPINProvider implements PINProvider {
+
+ protected static final Log log = LogFactory.getLog(SignPINProvider.class);
+
+ protected BKUGUIFacade gui;
+ protected SecureViewer viewer;
+ protected SignedInfoType signedInfo;
+ private boolean retry = false;
+
+ public SignPINProvider(BKUGUIFacade gui, SecureViewer viewer, SignedInfoType signedInfo) {
+ this.gui = gui;
+ this.viewer = viewer;
+ this.signedInfo = signedInfo;
+ }
+
+ @Override
+ public char[] providePIN(PINSpec spec, int retries)
+ throws CancelledException, InterruptedException {
+
+ gui.showSignaturePINDialog(spec, (retry) ? retries : -1,
+ this, "sign",
+ this, "cancel",
+ this, "secureViewer");
+
+ do {
+ log.trace("[" + Thread.currentThread().getName() + "] wait for action");
+ waitForAction();
+ log.trace("[" + Thread.currentThread().getName() + "] received action " + action);
+
+ if ("secureViewer".equals(action)) {
+ try {
+ viewer.displayDataToBeSigned(signedInfo, this, "pinEntry");
+ } catch (DigestException ex) {
+ log.error("Bad digest value: " + ex.getMessage());
+ gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH,
+ new Object[]{ex.getMessage()},
+ this, "error");
+ } catch (Exception ex) {
+ log.error("Could not display hashdata inputs: " +
+ ex.getMessage());
+ gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA,
+ new Object[]{ex.getMessage()},
+ this, "error");
+ }
+ } else if ("sign".equals(action)) {
+ gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT,
+ BKUGUIFacade.MESSAGE_WAIT);
+ retry = true;
+ return gui.getPin();
+ } else if ("pinEntry".equals(action)) {
+ gui.showSignaturePINDialog(spec, (retry) ? retries : -1,
+ this, "sign",
+ this, "cancel",
+ this, "secureViewer");
+ } else if ("cancel".equals(action) ||
+ "error".equals(action)) {
+ gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT,
+ BKUGUIFacade.MESSAGE_WAIT);
+ throw new CancelledException(spec.getLocalizedName() +
+ " entry cancelled");
+ } else {
+ log.error("unknown action command " + action);
+ }
+ } while (true);
+ }
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java
new file mode 100644
index 00000000..dc21492e
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINGUI.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.pin.gui;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.smcc.CancelledException;
+import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.pin.gui.PINGUI;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The number of retries is not fixed and there is no way (?) to obtain this value.
+ * A PINProvider should therefore maintain an internal retry counter or flag
+ * to decide whether or not to warn the user (num retries passed in providePIN).
+ *
+ * Therefore PINProvider objects should not be reused.
+ *
+ * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated)
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class VerifyPINGUI extends VerifyPINProvider implements PINGUI {
+
+ protected static final Log log = LogFactory.getLog(VerifyPINGUI.class);
+
+ private boolean retry = false;
+
+ public VerifyPINGUI(BKUGUIFacade gui) {
+ super(gui);
+ }
+
+ @Override
+ public void enterPINDirect(PINSpec spec, int retries)
+ throws CancelledException, InterruptedException {
+ gui.showEnterPINDirect(spec, (retry) ? retries : -1);
+ retry = true;
+ }
+
+ @Override
+ public void enterPIN(PINSpec spec, int retries) {
+ gui.showEnterPIN(spec, (retry) ? retries : -1);
+ retry = true;
+ }
+
+
+ @Override
+ public void validKeyPressed() {
+ gui.validKeyPressed();
+ }
+
+ @Override
+ public void correctionButtonPressed() {
+ gui.correctionButtonPressed();
+ }
+
+ @Override
+ public void allKeysCleared() {
+ gui.allKeysCleared();
+ }
+
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java
new file mode 100644
index 00000000..fda1e402
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.pin.gui;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.smcc.CancelledException;
+import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.pin.gui.PINProvider;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The number of retries is not fixed and there is no way (?) to obtain this value.
+ * A PINProvider should therefore maintain an internal retry counter or flag
+ * to decide whether or not to warn the user (num retries passed in providePIN).
+ *
+ * Therefore PINProvider objects should not be reused.
+ *
+ * (ACOS: reload counter: between 0 and 15, where 15 meens deactivated)
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class VerifyPINProvider extends AbstractPINProvider implements PINProvider {
+
+ protected static final Log log = LogFactory.getLog(VerifyPINProvider.class);
+
+ protected BKUGUIFacade gui;
+ private boolean retry = false;
+
+ public VerifyPINProvider(BKUGUIFacade gui) {
+ this.gui = gui;
+ }
+
+ @Override
+ public char[] providePIN(PINSpec spec, int retries)
+ throws CancelledException, InterruptedException {
+
+ gui.showVerifyPINDialog(spec, (retry) ? retries : -1,
+ this, "verify",
+ this, "cancel");
+
+ log.trace("[" + Thread.currentThread().getName() + "] wait for action");
+ waitForAction();
+ log.trace("[" + Thread.currentThread().getName() + "] received action " + action);
+
+ if ("cancel".equals(action)) {
+ gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT,
+ BKUGUIFacade.MESSAGE_WAIT);
+ throw new CancelledException(spec.getLocalizedName() +
+ " entry cancelled");
+ }
+
+ gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT,
+ BKUGUIFacade.MESSAGE_WAIT);
+ retry = true;
+ return gui.getPin();
+ }
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java
new file mode 100644
index 00000000..14b36e28
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.smccstal;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.smcc.SignatureCard;
+import at.gv.egiz.smcc.util.SMCCHelper;
+import at.gv.egiz.stal.QuitRequest;
+import at.gv.egiz.stal.STALRequest;
+import at.gv.egiz.stal.STALResponse;
+
+/**
+ * Abstract base class for AppletBKUWorker and LocalBKUWorker,
+ * providing card specific functionality not implemented by AbstractSMCCSTAL
+ * as well as common GUI functionality (action event handling).
+ * <br/>
+ * This class implements SMCCSTALRequestHandler and registers itself as QUIT handler.
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public abstract class AbstractBKUWorker extends AbstractSMCCSTAL implements ActionListener, SMCCSTALRequestHandler {
+
+ protected static Log log = LogFactory.getLog(AbstractBKUWorker.class);
+ protected BKUGUIFacade gui;
+ protected List<String> actionCommandList = new ArrayList<String>();
+ protected Boolean actionPerformed = false;
+ protected boolean finished = false;
+
+ public AbstractBKUWorker(BKUGUIFacade gui) {
+ if (gui == null) {
+ throw new NullPointerException("No BKU GUI provided");
+ }
+ this.gui = gui;
+// this.locale = gui.getLocale();
+ addRequestHandler(QuitRequest.class, this);
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ // Common action event handling //
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * notifies all registered handlers that an event occured
+ * @param e
+ */
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.info("Action: " + e);
+ if (actionCommandList != null) {
+ if (actionCommandList.contains(e.getActionCommand())) {
+ actionOccured();
+ }
+ } else {
+ actionOccured();
+ }
+ }
+
+ /**
+ * register for notification on action event
+ * @throws java.lang.InterruptedException
+ */
+ protected synchronized void waitForAction() throws InterruptedException {
+ log.info("Waiting for Action");
+ while (!actionPerformed) {
+ wait();
+ }
+ actionPerformed = false;
+ }
+
+ protected synchronized void actionOccured() {
+ log.info("Received Action");
+ actionPerformed = true;
+ notifyAll();
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ // card specific implementations of AbstractSMCCSTAL //
+ ///////////////////////////////////////////////////////////////////
+
+ @Override
+ protected boolean waitForCard() {
+ if (signatureCard != null) {
+ return false;
+ }
+ SMCCHelper smccHelper = new SMCCHelper();
+ actionCommandList.clear();
+ actionCommandList.add("cancel");
+ // while no sigcard found or cancel button pressed
+ int oldValue = SMCCHelper.PC_SC_NOT_SUPPORTED; // this is a save default
+ while ((signatureCard == null) && (!actionPerformed)) {
+ switch (smccHelper.getResultCode()) {
+ case SMCCHelper.PC_SC_NOT_SUPPORTED:
+ actionCommandList.clear();
+ actionCommandList.add("ok");
+ gui.showErrorDialog(BKUGUIFacade.ERR_NO_PCSC, null, this, "ok");
+ try {
+ waitForAction();
+ } catch (InterruptedException e) {
+ log.error(e);
+ }
+ return true;
+ case SMCCHelper.TERMINAL_NOT_PRESENT:
+ actionCommandList.clear();
+ actionCommandList.add("ok");
+ gui.showErrorDialog(BKUGUIFacade.ERR_NO_CARDTERMINAL, null, this, "ok");
+ try {
+ waitForAction();
+ } catch (InterruptedException e) {
+ log.error(e);
+ }
+ return true;
+ case SMCCHelper.CARD_NOT_SUPPORTED:
+ if (oldValue != SMCCHelper.CARD_NOT_SUPPORTED) {
+ actionCommandList.clear();
+ actionCommandList.add("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;
+ case SMCCHelper.NO_CARD:
+ if (oldValue != SMCCHelper.NO_CARD) {
+ actionCommandList.clear();
+ actionCommandList.add("cancel");
+ gui.showMessageDialog(BKUGUIFacade.TITLE_INSERTCARD,
+ BKUGUIFacade.MESSAGE_INSERTCARD, null,
+ BKUGUIFacade.BUTTON_CANCEL, this, "cancel");
+ oldValue = SMCCHelper.NO_CARD;
+ }
+ break;
+ case SMCCHelper.CARD_FOUND:
+ signatureCard = smccHelper.getSignatureCard(gui.getLocale());
+ return false;
+ }
+ smccHelper.update(3000);
+ }
+ return signatureCard == null;
+ }
+
+ @Override
+ protected BKUGUIFacade getGUI() {
+ return gui;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ // SMCCSTALRequestHandler for QUIT requests //
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Handle QUIT requests: set finished true.
+ * @param request a QUIT request
+ * @return null (no response on QUIT)
+ */
+ @Override
+ public STALResponse handleRequest(STALRequest request) {
+ if (request instanceof QuitRequest) {
+ log.info("Setting state to: finished for BKUWorker " + this);
+ finished = true;
+ } else {
+ log.error("Unexpected request to handle: " + request);
+ }
+ return null;
+ }
+
+ /**
+ * No initialization required for QUIT request handlers.
+ * @param sc
+ * @param gui
+ */
+ @Override
+ public void init(SignatureCard sc, BKUGUIFacade gui) {
+ }
+
+ /**
+ * QUIT request handlers do not require a card.
+ * @return false
+ */
+ @Override
+ public boolean requireCard() {
+ return false;
+ }
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java
new file mode 100644
index 00000000..98b21f79
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java
@@ -0,0 +1,86 @@
+/*
+* Copyright 2008 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package at.gv.egiz.bku.smccstal;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.smcc.SignatureCard;
+import at.gv.egiz.stal.STALRequest;
+import at.gv.egiz.stal.STALResponse;
+
+public abstract class AbstractRequestHandler implements SMCCSTALRequestHandler,
+ ActionListener {
+ private final static Log log = LogFactory
+ .getLog(AbstractRequestHandler.class);
+
+ protected SignatureCard card;
+ protected BKUGUIFacade gui;
+ protected static STALMessageConsumer messageConsumer = null;
+ protected String actionCommand;
+ protected boolean actionPerformed = false;
+
+ @Override
+ public abstract STALResponse handleRequest(STALRequest request) throws InterruptedException;
+
+ @Override
+ public void init(SignatureCard sc, BKUGUIFacade gui) {
+ if ((sc == null) || (gui == null)) {
+ throw new NullPointerException("Parameter must not be set to null");
+ }
+ this.card = sc;
+ this.gui = gui;
+ }
+
+ public static void setMessageConsumer(STALMessageConsumer messageConsumer) {
+ AbstractRequestHandler.messageConsumer = messageConsumer;
+ }
+
+ protected static void newSTALMessage(String caption, String message) {
+ if (messageConsumer != null) {
+ messageConsumer.consumeNewSTALMessage(caption, message);
+ }
+ }
+
+ protected synchronized void waitForAction() throws InterruptedException {
+ try {
+ while (!actionPerformed) {
+ wait();
+ }
+ } catch (InterruptedException e) {
+ log.error("interrupt in waitForAction");
+ throw e;
+ }
+ actionPerformed = false;
+ }
+
+ private synchronized void actionPerformed() {
+ actionPerformed = true;
+ notifyAll();
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ actionCommand = e.getActionCommand();
+ actionPerformed();
+ }
+
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java
new file mode 100644
index 00000000..d0762da9
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.smccstal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+//import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.smcc.SignatureCard;
+import at.gv.egiz.stal.ErrorResponse;
+import at.gv.egiz.stal.InfoboxReadRequest;
+import at.gv.egiz.stal.STAL;
+import at.gv.egiz.stal.STALRequest;
+import at.gv.egiz.stal.STALResponse;
+import at.gv.egiz.stal.StatusRequest;
+
+public abstract class AbstractSMCCSTAL implements STAL {
+ private static Log log = LogFactory.getLog(AbstractSMCCSTAL.class);
+
+ public final static int DEFAULT_MAX_RETRIES = 1;
+
+// protected Locale locale = Locale.getDefault();
+ protected SignatureCard signatureCard = null;
+ protected Map<String, SMCCSTALRequestHandler> handlerMap = new HashMap<String, SMCCSTALRequestHandler>();
+
+ protected int maxRetries = DEFAULT_MAX_RETRIES;
+ protected Set<Integer> unrecoverableErrors = new HashSet<Integer>();
+
+ protected AbstractSMCCSTAL() {
+ addRequestHandler(InfoboxReadRequest.class, new InfoBoxReadRequestHandler());
+ addRequestHandler(StatusRequest.class, new StatusRequestHandler());
+ unrecoverableErrors.add(6001);
+ }
+
+ /**
+ * Implementations must assign the signature card within this method.
+ *
+ * @return if the user canceled
+ */
+ protected abstract boolean waitForCard();
+
+ protected abstract BKUGUIFacade getGUI();
+
+ private STALResponse getResponse(STALRequest request) throws InterruptedException {
+ int retryCounter = 0;
+ while (retryCounter < maxRetries) {
+ log.info("Retry #" + retryCounter + " of " + maxRetries);
+ SMCCSTALRequestHandler handler = null;
+ handler = handlerMap.get(request.getClass().getSimpleName());
+ if (handler != null) {
+ if (handler.requireCard()) {
+ if (waitForCard()) {
+ return new ErrorResponse(6001);
+ }
+ }
+ try {
+ handler.init(signatureCard, getGUI());
+ STALResponse response = handler.handleRequest(request);
+ if (response != null) {
+ if (response instanceof ErrorResponse) {
+ log.info("Got an error response");
+ ErrorResponse err = (ErrorResponse) response;
+ if (unrecoverableErrors.contains(err.getErrorCode())) {
+ return response;
+ }
+ if ((++retryCounter < maxRetries) && (handler.requireCard())) {
+ signatureCard.disconnect(true);
+ signatureCard = null;
+ } else {
+ log.info("Exceeded max retries, returning error "
+ + err.getErrorMessage());
+ return response;
+ }
+ } else {
+ return response;
+ }
+ } else {
+ log.info("Got null response from handler, assuming quit");
+ return null;
+ }
+ } catch (InterruptedException e) {
+ log.info("Interrupt during request handling, do not retry");
+ throw e;
+ } catch (Exception e) {
+ log.info("Error while handling STAL request:", e);
+ if (++retryCounter < maxRetries) {
+ signatureCard.disconnect(true);
+ signatureCard = null;
+ } else {
+ log.info("Exceeded max retries, returning error.");
+ return new ErrorResponse(6000);
+ }
+ }
+ } else {
+ log.error("Cannot find a handler for STAL request: " + request);
+ return new ErrorResponse();
+ }
+ }
+ return new ErrorResponse(6000);
+ }
+
+ /**
+ *
+ * @param requestList
+ * @return
+ * @throws RuntimeException with cause InterruptedException if interrupted
+ */
+ @Override
+ public List<STALResponse> handleRequest(List<? extends STALRequest> requestList) {
+ log.debug("Got request list containing " + requestList.size()
+ + " STAL requests");
+ List<STALResponse> responseList = new ArrayList<STALResponse>(requestList
+ .size());
+ for (STALRequest request : requestList) {
+ log.info("Processing: " + request.getClass());
+ STALResponse response;
+ try {
+ response = getResponse(request);
+ if (response != null) {
+ responseList.add(response);
+ if (response instanceof ErrorResponse) {
+ log.info("Got an error response, don't process remaining requests");
+ break;
+ }
+ }
+ } catch (InterruptedException ex) {
+ log.error("interrupted during request handling");
+ throw new RuntimeException("interrupted during request handling", ex);
+ }
+
+ }
+ return responseList;
+ }
+
+ public void addRequestHandler(Class<? extends STALRequest> id,
+ SMCCSTALRequestHandler handler) {
+ log.debug("Registering STAL request handler: " + id.getSimpleName());
+ handlerMap.put(id.getSimpleName(), handler);
+ }
+
+ public void removeRequestHandler(Class<? extends STALRequest> id) {
+ log.debug("De-registering STAL request handler: " + id.getSimpleName());
+ handlerMap.remove(id.getSimpleName());
+ }
+
+ public SMCCSTALRequestHandler getRequestHandler(
+ Class<? extends STALRequest> request) {
+ return handlerMap.get(request.getSimpleName());
+ }
+
+// @Override
+// public void setLocale(Locale locale) {
+// if (locale == null) {
+// throw new NullPointerException("Locale must not be set to null");
+// }
+// this.locale = locale;
+// }
+
+ public void setMaxRetries(int maxRetries) {
+ this.maxRetries = maxRetries;
+ }
+
+ public Set<Integer> getUnrecoverableErrors() {
+ return unrecoverableErrors;
+ }
+
+ public void setUnrecoverableErrors(Set<Integer> unrecoverableErrors) {
+ this.unrecoverableErrors = unrecoverableErrors;
+ }
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java
new file mode 100644
index 00000000..3a564b91
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java
@@ -0,0 +1,85 @@
+/*
+* Copyright 2008 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package at.gv.egiz.bku.smccstal;
+
+import iaik.me.asn1.ASN1;
+import iaik.me.utils.Base64;
+
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Vector;
+
+public class DomainIdConverter {
+
+ private static String getBaseId(ASN1 identityLink) throws IOException {
+
+ if (identityLink.getType() == ASN1.TYPE_SEQUENCE) {
+ ASN1 personData = identityLink.getElementAt(4);
+ if (personData.getType() == ASN1.TAG_CONTEXT_SPECIFIC) {
+ ASN1 physicalPersonData = personData.gvASN1();
+ ASN1 baseId = physicalPersonData.getElementAt(0);
+ return baseId.gvString();
+ }
+ throw new IOException("Invalid structure.");
+
+ }
+ throw new IOException("Invalid structure.");
+
+ }
+
+ private static ASN1 replaceBaseId(ASN1 identityLink, String newBaseId)
+ throws IOException {
+
+ ASN1 newIdentityLink = new ASN1(ASN1.TYPE_SEQUENCE, new Vector<ASN1>());
+ for (int i = 0; i < identityLink.getSize(); i++) {
+ ASN1 asn1 = identityLink.getElementAt(i);
+ if (i == 4 && asn1.getType() == ASN1.TAG_CONTEXT_SPECIFIC) {
+ ASN1 physicalPersonData = asn1.gvASN1();
+ ASN1 newPhysicalPersonData = new ASN1(ASN1.TYPE_SEQUENCE,
+ new Vector<ASN1>());
+ newPhysicalPersonData.addElement(new ASN1(ASN1.TYPE_UTF8_STRING,
+ newBaseId));
+ for (int j = 1; j < physicalPersonData.getSize(); j++) {
+ newPhysicalPersonData.addElement(physicalPersonData.getElementAt(j));
+ }
+ asn1 = new ASN1(ASN1.TAG_CONTEXT_SPECIFIC, newPhysicalPersonData);
+ }
+ newIdentityLink.addElement(asn1);
+ }
+ return newIdentityLink;
+
+ }
+
+ public static byte[] convertDomainId(byte[] data, String domainId)
+ throws IOException, NoSuchAlgorithmException {
+ if (domainId == null) {
+ return data;
+ }
+ ASN1 identityLink = new ASN1(data);
+ MessageDigest sha = null;
+ sha = MessageDigest.getInstance("SHA");
+ String base = getBaseId(identityLink);
+ sha.update((base + "+" + domainId).getBytes());
+ String bpkStr = new String(Base64.encode(sha.digest()));
+ bpkStr = bpkStr.trim();
+ identityLink = replaceBaseId(identityLink, bpkStr);
+ System.out.println(getBaseId(identityLink));
+ return identityLink.getEncoded();
+ }
+
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java
new file mode 100644
index 00000000..59700d4a
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/HashDataInputDisplay.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.smccstal;
+
+import at.gv.egiz.stal.signedinfo.ReferenceType;
+import java.security.DigestException;
+import java.util.List;
+
+/**
+ *
+ * @author clemens
+ */
+public interface HashDataInputDisplay {
+
+
+ /**
+ * TODO: (see AbstractHelpListener)
+ *
+ *
+ * Displays the hashdata inputs for all provided dsig:SignedReferences.
+ * Implementations may verify the digest value if necessary.
+ * (LocalSignRequestHandler operates on DataObjectHashDataInput,
+ * other SignRequestHandlers should cache the HashDataInputs obtained by webservice calls,
+ * or simply forward to a HashDataInputServlet.)
+ * @param signedReferences The caller may select a subset of the references in SignedInfo to be displayed.
+ * @throws java.security.DigestException if digest values are verified and do not correspond
+ * (or any other digest computation error occurs)
+ * @throws java.lang.Exception
+ */
+ void displayHashDataInputs(List<ReferenceType> signedReferences) throws DigestException, Exception;
+
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java
new file mode 100644
index 00000000..b34ab862
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java
@@ -0,0 +1,141 @@
+/*
+* 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.bku.pin.gui.VerifyPINGUI;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.smcc.CancelledException;
+import at.gv.egiz.smcc.LockedException;
+import at.gv.egiz.smcc.NotActivatedException;
+import at.gv.egiz.smcc.SignatureCard;
+import at.gv.egiz.smcc.SignatureCardException;
+import at.gv.egiz.stal.ErrorResponse;
+import at.gv.egiz.stal.InfoboxReadRequest;
+import at.gv.egiz.stal.InfoboxReadResponse;
+import at.gv.egiz.stal.STALRequest;
+import at.gv.egiz.stal.STALResponse;
+
+public class InfoBoxReadRequestHandler extends AbstractRequestHandler {
+
+ private static Log log = LogFactory.getLog(InfoBoxReadRequestHandler.class);
+
+// protected PINProviderFactory pinProviderFactory;
+
+ @Override
+ public STALResponse handleRequest(STALRequest request) throws InterruptedException {
+ if (request instanceof InfoboxReadRequest) {
+ InfoboxReadRequest infoBox = (InfoboxReadRequest) request;
+
+ try {
+ if (infoBox.getInfoboxIdentifier().equals("IdentityLink")) {
+ newSTALMessage("Message.RequestCaption", "Message.IdentityLink");
+ log.debug("Handling identitylink infobox");
+ byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(),
+ new VerifyPINGUI(gui),
+ infoBox.getDomainIdentifier());
+ if (resp == null) {
+ log.info("Infobox doesn't contain any data. Assume card is not activated.");
+ throw new NotActivatedException();
+ } else {
+ try {
+ resp = DomainIdConverter.convertDomainId(resp, infoBox
+ .getDomainIdentifier());
+ } catch (Exception e) {
+ log.error("Cannot convert domain specific id", e);
+ return new ErrorResponse(1000);
+ }
+ }
+ InfoboxReadResponse stalResp = new InfoboxReadResponse();
+ stalResp.setInfoboxValue(resp);
+ return stalResp;
+ } else if (SignatureCard.KeyboxName.CERITIFIED_KEYPAIR.equals(infoBox
+ .getInfoboxIdentifier())) {
+ newSTALMessage("Message.RequestCaption", "Message.CertifiedKeypair");
+ log.debug("Handling certified keypair infobox");
+ byte[] resp = card
+ .getCertificate(SignatureCard.KeyboxName.CERITIFIED_KEYPAIR);
+ if (resp == null) {
+ return new ErrorResponse(6001);
+ }
+ InfoboxReadResponse stalResp = new InfoboxReadResponse();
+ stalResp.setInfoboxValue(resp);
+ return stalResp;
+ } else if (SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR
+ .equals(infoBox.getInfoboxIdentifier())) {
+ newSTALMessage("Message.RequestCaption",
+ "Message.SecureSignatureKeypair");
+ log.debug("Handling secure signature keypair infobox");
+ byte[] resp = card
+ .getCertificate(SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR);
+ if (resp == null) {
+ return new ErrorResponse(6001);
+ }
+ InfoboxReadResponse stalResp = new InfoboxReadResponse();
+ stalResp.setInfoboxValue(resp);
+ return stalResp;
+ } else {
+ newSTALMessage("Message.RequestCaption", "Message.InfoboxReadRequest");
+ log.warn("Unknown infobox identifier: "
+ + infoBox.getInfoboxIdentifier() + " trying generic request");
+ byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(),
+ new VerifyPINGUI(gui),
+ infoBox.getDomainIdentifier());
+ if (resp == null) {
+ return new ErrorResponse(6001);
+ }
+ InfoboxReadResponse stalResp = new InfoboxReadResponse();
+ stalResp.setInfoboxValue(resp);
+ return stalResp;
+ }
+ } catch (IllegalArgumentException e) {
+ log.info("Infobox " + infoBox.getInfoboxIdentifier() + " not supported.");
+ return new ErrorResponse(4002);
+ } catch (NotActivatedException e) {
+ log.info("Citizen card not activated.", e);
+ gui.showErrorDialog(BKUGUIFacade.ERR_CARD_NOTACTIVATED, null, this, null);
+ waitForAction();
+ 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.showMessageDialog(BKUGUIFacade.TITLE_WAIT,
+ BKUGUIFacade.MESSAGE_WAIT);
+ return new ErrorResponse(6001);
+ } catch (CancelledException cx) {
+ log.debug("User cancelled request", cx);
+ return new ErrorResponse(6001);
+ } catch (SignatureCardException e) {
+ log.info("Error while reading infobox: " + e);
+ return new ErrorResponse(4000);
+ }
+ } else {
+ log.fatal("Got unexpected STAL request: " + request);
+ return new ErrorResponse(1000);
+ }
+ }
+
+ @Override
+ public boolean requireCard() {
+ return true;
+ }
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java
new file mode 100644
index 00000000..f19b3ef3
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.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.smccstal;
+
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.smcc.SignatureCard;
+import at.gv.egiz.stal.STALRequest;
+import at.gv.egiz.stal.STALResponse;
+
+public interface SMCCSTALRequestHandler {
+
+ public void init(SignatureCard sc, BKUGUIFacade gui);
+
+ public STALResponse handleRequest(STALRequest request) throws InterruptedException;
+
+ public boolean requireCard();
+
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java
new file mode 100644
index 00000000..7d7a6ec0
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java
@@ -0,0 +1,21 @@
+/*
+* Copyright 2008 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package at.gv.egiz.bku.smccstal;
+
+public interface STALMessageConsumer {
+ public void consumeNewSTALMessage(String captionId, String messageId);
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java
new file mode 100644
index 00000000..2ee37dc1
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.smccstal;
+
+import at.gv.egiz.stal.signedinfo.SignedInfoType;
+import java.awt.event.ActionListener;
+import java.security.DigestException;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+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(SignedInfoType signedInfo,
+ ActionListener okListener, String okCommand)
+ 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
new file mode 100644
index 00000000..5b436d16
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.smccstal;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.bku.pin.gui.SignPINGUI;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.smcc.CancelledException;
+import at.gv.egiz.smcc.LockedException;
+import at.gv.egiz.smcc.NotActivatedException;
+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.STALRequest;
+import at.gv.egiz.stal.STALResponse;
+import at.gv.egiz.stal.SignRequest;
+import at.gv.egiz.stal.SignResponse;
+import at.gv.egiz.stal.signedinfo.ObjectFactory;
+import at.gv.egiz.stal.signedinfo.SignedInfoType;
+
+public class SignRequestHandler extends AbstractRequestHandler {
+
+ private static Log log = LogFactory.getLog(SignRequestHandler.class);
+ private static JAXBContext jaxbContext;
+
+ static {
+ try {
+ jaxbContext = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName());
+ } catch (JAXBException e) {
+ log.fatal("Cannot init jaxbContext", e);
+ }
+ }
+
+ protected SecureViewer secureViewer;
+
+ public SignRequestHandler(SecureViewer secureViewer) {
+ this.secureViewer = secureViewer;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public STALResponse handleRequest(STALRequest request) throws InterruptedException {
+ if (request instanceof SignRequest) {
+ SignRequest signReq = (SignRequest) request;
+ newSTALMessage("Message.RequestCaption", "Message.SignRequest");
+ try {
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ InputStream is = new ByteArrayInputStream(signReq.getSignedInfo());
+ JAXBElement<SignedInfoType> si = (JAXBElement<SignedInfoType>) unmarshaller.unmarshal(is);
+ String signatureMethod = si.getValue().getSignatureMethod().getAlgorithm();
+ log.debug("Found signature method: " + signatureMethod);
+ KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier());
+
+ byte[] resp = card.createSignature(new ByteArrayInputStream(signReq.getSignedInfo()), kb,
+ new SignPINGUI(gui, secureViewer, si.getValue()), signatureMethod);
+ if (resp == null) {
+ return new ErrorResponse(6001);
+ }
+ SignResponse stalResp = new SignResponse();
+ stalResp.setSignatureValue(resp);
+ return stalResp;
+ } catch (NotActivatedException e) {
+ log.info("Citizen card not activated.", e);
+ gui.showErrorDialog(BKUGUIFacade.ERR_CARD_NOTACTIVATED, null, this, null);
+ waitForAction();
+ 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.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);
+ } catch (JAXBException e) {
+ log.error("Cannot unmarshall signed info", e);
+ return new ErrorResponse(1000);
+ } catch (IOException e) {
+ log.error("Error while creating signature: " + e);
+ return new ErrorResponse(4000);
+ }
+ } else {
+ log.fatal("Got unexpected STAL request: " + request);
+ return new ErrorResponse(1000);
+ }
+ }
+
+ @Override
+ public boolean requireCard() {
+ return true;
+ }
+
+}
diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/StatusRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/StatusRequestHandler.java
new file mode 100644
index 00000000..56b24920
--- /dev/null
+++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/StatusRequestHandler.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.smccstal;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.smcc.SignatureCard;
+import at.gv.egiz.smcc.util.SMCCHelper;
+import at.gv.egiz.stal.ErrorResponse;
+import at.gv.egiz.stal.STALRequest;
+import at.gv.egiz.stal.STALResponse;
+import at.gv.egiz.stal.StatusRequest;
+import at.gv.egiz.stal.StatusResponse;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class StatusRequestHandler extends AbstractRequestHandler {
+
+ protected static final Log log = LogFactory.getLog(StatusRequestHandler.class);
+
+ @Override
+ public void init(SignatureCard sc, BKUGUIFacade gui) {
+ //nothing, avoid NullPointerEx since requireCard==false => sc==null
+ }
+
+
+ @Override
+ public STALResponse handleRequest(STALRequest request) throws InterruptedException {
+
+ if (request instanceof StatusRequest) {
+ log.info("handling STATUS request");
+ SMCCHelper smccHelper = new SMCCHelper();
+ StatusResponse response = new StatusResponse();
+ if (log.isTraceEnabled()) {
+ log.trace("SMCC result code: " + smccHelper.getResultCode() +
+ ", cardReady: " +
+ (smccHelper.getResultCode() == SMCCHelper.CARD_FOUND));
+ }
+ if (smccHelper.getResultCode() == SMCCHelper.CARD_FOUND) {
+ response.setCardReady(Boolean.TRUE);
+ } else {
+ response.setCardReady(Boolean.FALSE);
+ }
+ return response;
+ } else {
+ log.error("Got unexpected STAL request: " + request);
+ return new ErrorResponse(1000);
+ }
+ }
+
+ @Override
+ public boolean requireCard() {
+ return false;
+ }
+}
diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java
new file mode 100644
index 00000000..f2d61e7f
--- /dev/null
+++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java
@@ -0,0 +1,105 @@
+/*
+* Copyright 2008 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package at.gv.egiz.smcc;
+
+import iaik.me.asn1.ASN1;
+import iaik.me.utils.Base64;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Vector;
+
+import org.junit.Ignore;
+
+@Ignore
+public class ASN1Test {
+
+ public static void main(String[] args) throws IOException {
+
+ ClassLoader classLoader = ASN1Test.class.getClassLoader();
+
+ InputStream stream = classLoader.getResourceAsStream("IdentityLink.bin");
+
+ if (stream != null) {
+
+ ASN1 identityLink = new ASN1(stream);
+ System.out.println("BaseId:" + getBaseId(identityLink));
+ identityLink = replaceBaseId(identityLink, "test");
+ System.out.println("BaseId:" + getBaseId(identityLink));
+
+ String bpk = "hansi";
+ MessageDigest sha = null;
+ try {
+ sha = MessageDigest.getInstance("SHA");
+ } catch (NoSuchAlgorithmException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ sha.update((identityLink + "+" + bpk).getBytes());
+ String bpkStr = new String(Base64.encode(sha.digest()));
+ System.out.println("bpk: "+bpkStr);
+ identityLink = replaceBaseId(identityLink, bpkStr);
+ System.out.println(getBaseId(identityLink));
+
+ } else {
+ System.out.println("Not found.");
+ }
+
+ }
+
+ private static String getBaseId(ASN1 identityLink) throws IOException {
+
+ if (identityLink.getType() == ASN1.TYPE_SEQUENCE) {
+ ASN1 personData = identityLink.getElementAt(4);
+ if (personData.getType() == ASN1.TAG_CONTEXT_SPECIFIC) {
+ ASN1 physicalPersonData = personData.gvASN1();
+ ASN1 baseId = physicalPersonData.getElementAt(0);
+ return baseId.gvString();
+ }
+ throw new IOException("Invalid structure.");
+
+ }
+ throw new IOException("Invalid structure.");
+
+ }
+
+ private static ASN1 replaceBaseId(ASN1 identityLink, String newBaseId)
+ throws IOException {
+
+ ASN1 newIdentityLink = new ASN1(ASN1.TYPE_SEQUENCE, new Vector<ASN1>());
+ for (int i = 0; i < identityLink.getSize(); i++) {
+ ASN1 asn1 = identityLink.getElementAt(i);
+ if (i == 4 && asn1.getType() == ASN1.TAG_CONTEXT_SPECIFIC) {
+ ASN1 physicalPersonData = asn1.gvASN1();
+ ASN1 newPhysicalPersonData = new ASN1(ASN1.TYPE_SEQUENCE,
+ new Vector<ASN1>());
+ newPhysicalPersonData.addElement(new ASN1(ASN1.TYPE_UTF8_STRING,
+ newBaseId));
+ for (int j = 1; j < physicalPersonData.getSize(); j++) {
+ newPhysicalPersonData.addElement(physicalPersonData.getElementAt(j));
+ }
+ asn1 = new ASN1(ASN1.TAG_CONTEXT_SPECIFIC, newPhysicalPersonData);
+ }
+ newIdentityLink.addElement(asn1);
+ }
+ return newIdentityLink;
+
+ }
+
+}
diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java
new file mode 100644
index 00000000..bf57b0a6
--- /dev/null
+++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java
@@ -0,0 +1,126 @@
+package at.gv.egiz.smcc;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import javax.smartcardio.Card;
+import javax.smartcardio.CardTerminal;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.bku.smccstal.AbstractSMCCSTAL;
+import at.gv.egiz.bku.smccstal.SMCCSTALRequestHandler;
+import at.gv.egiz.smcc.pin.gui.PINGUI;
+import at.gv.egiz.stal.ErrorResponse;
+import at.gv.egiz.stal.InfoboxReadRequest;
+import at.gv.egiz.stal.InfoboxReadResponse;
+import at.gv.egiz.stal.STALRequest;
+import at.gv.egiz.stal.STALResponse;
+
+public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements
+ SMCCSTALRequestHandler {
+ private int errorConter;
+
+ @Override
+ protected BKUGUIFacade getGUI() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected boolean waitForCard() {
+ signatureCard = new SignatureCard() {
+
+ @Override
+ public byte[] createSignature(InputStream input, KeyboxName keyboxName,
+ PINGUI provider, String alg) throws SignatureCardException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void disconnect(boolean reset) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public byte[] getCertificate(KeyboxName keyboxName)
+ throws SignatureCardException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public byte[] getInfobox(String infobox, PINGUI provider,
+ String domainId) throws SignatureCardException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void init(Card card, CardTerminal cardTerminal) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setLocale(Locale locale) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Card getCard() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void reset() throws SignatureCardException {
+ // TODO Auto-generated method stub
+
+ }
+ };
+ return false;
+ }
+
+ @Before
+ public void setUp() {
+ addRequestHandler(InfoboxReadRequest.class, this);
+ }
+
+ @Test
+ @Ignore
+ public void testRetry() {
+ InfoboxReadRequest irr = new InfoboxReadRequest();
+ List<STALRequest> irrl = new ArrayList<STALRequest>();
+ irrl.add(irr);
+ List<STALResponse> list = handleRequest(irrl);
+ Assert.assertFalse(list.get(0) instanceof ErrorResponse);
+ }
+
+ @Override
+ public STALResponse handleRequest(STALRequest request) {
+ if (++errorConter < 3) {
+ return new ErrorResponse(400);
+ }
+ return new InfoboxReadResponse();
+ }
+
+ @Override
+ public void init(SignatureCard sc, BKUGUIFacade gui) {
+ }
+
+ @Override
+ public boolean requireCard() {
+ return true;
+ }
+
+}
diff --git a/smccSTAL/src/test/resources/log4j.properties b/smccSTAL/src/test/resources/log4j.properties
new file mode 100644
index 00000000..053eac17
--- /dev/null
+++ b/smccSTAL/src/test/resources/log4j.properties
@@ -0,0 +1,19 @@
+# loglever DEBUG, appender STDOUT
+log4j.rootLogger=TRACE, STDOUT
+#log4j.logger.at.gv.egiz.slbinding.RedirectEventFilter=DEBUG, STDOUT
+
+# STDOUT appender
+log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
+log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
+#log4j.appender.STDOUT.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %20c | %10t | %m%n
+#log4j.appender.STDOUT.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+log4j.appender.STDOUT.layout.ConversionPattern=%-5p |%d | %t | %c %x- %m%n
+
+### FILE appender
+#log4j.appender.file=org.apache.log4j.RollingFileAppender
+#log4j.appender.file.maxFileSize=100KB
+#log4j.appender.file.maxBackupIndex=9
+#log4j.appender.file.File=egovbus_ca.log
+#log4j.appender.file.threshold=info
+#log4j.appender.file.layout=org.apache.log4j.PatternLayout
+#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n \ No newline at end of file