From 9e50f1a103a37d9dcfbeb5ea45bcf6c6c0c0f6dd Mon Sep 17 00:00:00 2001 From: Tobias Kellner Date: Thu, 27 Nov 2014 20:57:33 +0100 Subject: Implement PDF-AS 4 changes --- .../asit/pdfover/gui/bku/mobile/ATrustHandler.java | 238 ++++++++++++++++ .../asit/pdfover/gui/bku/mobile/ATrustStatus.java | 86 ++++++ .../bku/mobile/AbstractMobileBKUStatusImpl.java | 138 +++++++++ .../asit/pdfover/gui/bku/mobile/IAIKHandler.java | 312 +++++++++++++++++++++ .../at/asit/pdfover/gui/bku/mobile/IAIKStatus.java | 80 ++++++ .../pdfover/gui/bku/mobile/MobileBKUHandler.java | 264 +++++++++++++++++ .../pdfover/gui/bku/mobile/MobileBKUHelper.java | 158 +++++++++++ .../pdfover/gui/bku/mobile/MobileBKUStatus.java | 140 +++++++++ .../at/asit/pdfover/gui/bku/mobile/MobileBKUs.java | 27 ++ .../gui/bku/mobile/SimpleXMLTrustManager.java | 225 +++++++++++++++ .../gui/bku/mobile/TrustedSocketFactory.java | 192 +++++++++++++ 11 files changed, 1860 insertions(+) create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/ATrustHandler.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/ATrustStatus.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/AbstractMobileBKUStatusImpl.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/IAIKHandler.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/IAIKStatus.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUHandler.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUHelper.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUStatus.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUs.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/SimpleXMLTrustManager.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/TrustedSocketFactory.java (limited to 'pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile') diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/ATrustHandler.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/ATrustHandler.java new file mode 100644 index 00000000..3af0bd1d --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/ATrustHandler.java @@ -0,0 +1,238 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +// Imports +import java.io.IOException; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.methods.PostMethod; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asit.pdfover.gui.bku.BKUHelper; +import at.asit.pdfover.gui.controls.Dialog; +import at.asit.pdfover.gui.controls.Dialog.BUTTONS; +import at.asit.pdfover.gui.controls.Dialog.ICON; +import at.asit.pdfover.gui.utils.Messages; +import at.asit.pdfover.gui.workflow.states.MobileBKUState; +import at.asit.pdfover.signator.SLResponse; + +/** + * A-Trust mobile BKU handler + */ +public class ATrustHandler extends MobileBKUHandler { + Shell shell; + + /** + * @param state + * @param shell + */ + public ATrustHandler(MobileBKUState state, Shell shell) { + super(state); + this.shell = shell; + } + + /** + * SLF4J Logger instance + **/ + private static final Logger log = LoggerFactory + .getLogger(ATrustHandler.class); + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleSLRequestResponse(java.lang.String) + */ + @Override + public void handleSLRequestResponse(String responseData) throws Exception { + ATrustStatus status = getStatus(); + + // Extract infos: + String sessionID = MobileBKUHelper.extractTag(responseData, + "identification.aspx?sid=", "\""); //$NON-NLS-1$ //$NON-NLS-2$ + + String viewState = MobileBKUHelper.extractTag(responseData, + "id=\"__VIEWSTATE\" value=\"", "\""); //$NON-NLS-1$ //$NON-NLS-2$ + + String eventValidation = MobileBKUHelper.extractTag(responseData, + "id=\"__EVENTVALIDATION\" value=\"", "\""); //$NON-NLS-1$ //$NON-NLS-2$ + + log.info("sessionID: " + sessionID); //$NON-NLS-1$ + log.info("viewState: " + viewState); //$NON-NLS-1$ + log.info("eventValidation: " + eventValidation); //$NON-NLS-1$ + + status.setSessionID(sessionID); + + status.setViewstate(viewState); + + status.setEventvalidation(eventValidation); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#postCredentials() + */ + @Override + public String postCredentials() throws Exception { + ATrustStatus status = getStatus(); + + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = BKUHelper.getHttpClient(); + + PostMethod post = new PostMethod(status.getBaseURL() + "/identification.aspx?sid=" + status.getSessionID()); //$NON-NLS-1$ + post.getParams().setContentCharset("utf-8"); //$NON-NLS-1$ + post.addParameter("__VIEWSTATE", status.getViewstate()); //$NON-NLS-1$ + post.addParameter("__EVENTVALIDATION", status.getEventvalidation()); //$NON-NLS-1$ + post.addParameter("handynummer", status.getPhoneNumber()); //$NON-NLS-1$ + post.addParameter("signaturpasswort", status.getMobilePassword()); //$NON-NLS-1$ + post.addParameter("Button_Identification", "Identifizieren"); //$NON-NLS-1$ //$NON-NLS-2$ + + return executePost(client, post); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleCredentialsResponse(java.lang.String) + */ + @Override + public void handleCredentialsResponse(String responseData) throws Exception { + ATrustStatus status = getStatus(); + String viewState = status.getViewstate(); + String eventValidation = status.getEventvalidation(); + String sessionID = status.getSessionID(); + String refVal = null; + String signatureDataURL = null; + + status.setErrorMessage(null); + + if (responseData.contains("signature.aspx?sid=")) { //$NON-NLS-1$ + // credentials ok! TAN entry + sessionID = MobileBKUHelper.extractTag(responseData, "signature.aspx?sid=", "\""); //$NON-NLS-1$ //$NON-NLS-2$ + viewState = MobileBKUHelper.extractTag(responseData, "id=\"__VIEWSTATE\" value=\"", "\""); //$NON-NLS-1$ //$NON-NLS-2$ + eventValidation = MobileBKUHelper.extractTag(responseData, "id=\"__EVENTVALIDATION\" value=\"", "\""); //$NON-NLS-1$ //$NON-NLS-2$ + refVal = MobileBKUHelper.extractTag(responseData, "id='vergleichswert'>Vergleichswert:", ""); //$NON-NLS-1$//$NON-NLS-2$ + signatureDataURL = status.getBaseURL() + "/ShowSigobj.aspx" + //$NON-NLS-1$ + MobileBKUHelper.extractTag(responseData, "ShowSigobj.aspx", "'"); //$NON-NLS-1$//$NON-NLS-2$ + } else if (responseData.contains("sl:InfoboxReadResponse")) { //$NON-NLS-1$ + // credentials ok! InfoboxReadResponse + getSigningState().setSignatureResponse( + new SLResponse(responseData, getStatus().getServer(), null, null)); + return; + } else { + + // error page + // extract error text! + String errorMessage = MobileBKUHelper.extractTag(responseData, "", ""); //$NON-NLS-1$ //$NON-NLS-2$ + + status.setErrorMessage(errorMessage); + + // force UI again! + status.setMobilePassword(null); + } + + log.info("sessionID: " + sessionID); //$NON-NLS-1$ + log.info("Vergleichswert: " + refVal); //$NON-NLS-1$ + log.info("viewState: " + viewState); //$NON-NLS-1$ + log.info("eventValidation: " + eventValidation); //$NON-NLS-1$ + log.info("signatureDataURL: " + signatureDataURL); //$NON-NLS-1$ + + status.setSessionID(sessionID); + status.setRefVal(refVal); + status.setViewstate(viewState); + status.setEventvalidation(eventValidation); + status.setSignatureDataURL(signatureDataURL); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#postTAN() + */ + @Override + public String postTAN() throws IOException { + ATrustStatus status = getStatus(); + + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = BKUHelper.getHttpClient(); + + PostMethod post = new PostMethod(status.getBaseURL() + + "/signature.aspx?sid=" + status.getSessionID()); //$NON-NLS-1$ + post.getParams().setContentCharset("utf-8"); //$NON-NLS-1$ + post.addParameter("__VIEWSTATE", status.getViewstate()); //$NON-NLS-1$ + post.addParameter( + "__EVENTVALIDATION", status.getEventvalidation()); //$NON-NLS-1$ + post.addParameter("input_tan", status.getTan()); //$NON-NLS-1$ + post.addParameter("SignButton", "Signieren"); //$NON-NLS-1$ //$NON-NLS-2$ + post.addParameter("Button1", "Identifizieren"); //$NON-NLS-1$ //$NON-NLS-2$ + + return executePost(client, post); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleTANResponse(java.lang.String) + */ + @Override + public void handleTANResponse(String responseData) { + getStatus().setErrorMessage(null); + if (responseData.contains("sl:CreateXMLSignatureResponse xmlns:sl") || //$NON-NLS-1$ + responseData.contains("sl:CreateCMSSignatureResponse xmlns:sl")) { //$NON-NLS-1$ + // success !! + + getSigningState().setSignatureResponse( + new SLResponse(responseData, getStatus().getServer(), null, null)); + } else { + try { + String tries = MobileBKUHelper.extractTag( + responseData, "Sie haben noch", "Versuch"); //$NON-NLS-1$ //$NON-NLS-2$ + getStatus().setTanTries(Integer.parseInt(tries.trim())); + getStatus().setErrorMessage("mobileBKU.wrong_tan"); //$NON-NLS-1$ + } catch (Exception e) { + getStatus().setTanTries(getStatus().getTanTries() - 1); + log.debug("Error parsing TAN response", e); //$NON-NLS-1$ + } + + if (getStatus().getTanTries() <= 0) { + getStatus().setErrorMessage(null); + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + Dialog dialog = new Dialog(ATrustHandler.this.shell, Messages.getString("common.warning"), //$NON-NLS-1$ + Messages.getString("mobileBKU.tan_tries_exceeded"), //$NON-NLS-1$ + BUTTONS.OK_CANCEL, ICON.QUESTION); + if (dialog.open() == SWT.CANCEL) { + // Go back to BKU Selection + getStatus().setTanTries(-1); + } else { + // Start signature process over + getStatus().setTanTries(-2); + } + } + }); + } + } + } + + @Override + public ATrustStatus getStatus() { + return (ATrustStatus) getState().getStatus(); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.bku.mobile.MobileBKUHandler#useBase64Request() + */ + @Override + protected boolean useBase64Request() { + return false; + } +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/ATrustStatus.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/ATrustStatus.java new file mode 100644 index 00000000..3fedf73e --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/ATrustStatus.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +// Imports +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asit.pdfover.gui.workflow.config.ConfigProvider; + +/** + * A-Trust MobileBKUStatus implementation + */ +public class ATrustStatus extends AbstractMobileBKUStatusImpl { + /** + * SLF4J Logger instance + **/ + @SuppressWarnings("unused") + private static final Logger log = LoggerFactory + .getLogger(ATrustStatus.class); + + /** Maximum number of TAN tries */ + public static final int MOBILE_MAX_TAN_TRIES = 3; + + private String viewstate; + private String eventvalidation; + + /** + * Constructor + * @param provider the ConfigProvider + */ + public ATrustStatus(ConfigProvider provider) { + setPhoneNumber(provider.getDefaultMobileNumber()); + setMobilePassword(provider.getDefaultMobilePassword()); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUStatus#getMaxTanTries() + */ + @Override + public int getMaxTanTries() { + return MOBILE_MAX_TAN_TRIES; + } + + /** + * @return the viewstate + */ + public String getViewstate() { + return this.viewstate; + } + + /** + * @param viewstate + * the viewstate to set + */ + public void setViewstate(String viewstate) { + this.viewstate = viewstate; + } + + /** + * @return the eventvalidation + */ + public String getEventvalidation() { + return this.eventvalidation; + } + + /** + * @param eventvalidation the eventvalidation to set + */ + public void setEventvalidation(String eventvalidation) { + this.eventvalidation = eventvalidation; + } +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/AbstractMobileBKUStatusImpl.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/AbstractMobileBKUStatusImpl.java new file mode 100644 index 00000000..e27fda6a --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/AbstractMobileBKUStatusImpl.java @@ -0,0 +1,138 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +/** + * Basic implementation of a MobileBKUStatus + */ +public abstract class AbstractMobileBKUStatusImpl implements MobileBKUStatus { + + private String sessionID; + private String phoneNumber; + private String mobilePassword; + private String baseURL; + private String refVal; + private String errorMessage; + private String tan; + private String server; + private String signatureDataURL; + private int tanTries = getMaxTanTries(); + + @Override + public int getTanTries() { + return this.tanTries; + } + + @Override + public void setTanTries(int tries) { + this.tanTries = tries; + } + + @Override + public String getTan() { + return this.tan; + } + + @Override + public void setTan(String tan) { + this.tan = tan; + } + + @Override + public String getErrorMessage() { + return this.errorMessage; + } + + @Override + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + @Override + public String getRefVal() { + return this.refVal; + } + + @Override + public void setRefVal(String refVal) { + this.refVal = refVal; + } + + @Override + public String getBaseURL() { + return this.baseURL; + } + + @Override + public void setBaseURL(String baseURL) { + this.baseURL = baseURL; + } + + @Override + public String getPhoneNumber() { + return this.phoneNumber; + } + + @Override + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + @Override + public String getMobilePassword() { + return this.mobilePassword; + } + + @Override + public void setMobilePassword(String mobilePassword) { + this.mobilePassword = mobilePassword; + } + + @Override + public String getSessionID() { + return this.sessionID; + } + + @Override + public void setSessionID(String sessionID) { + this.sessionID = sessionID; + } + + @Override + public String getServer() { + return this.server; + } + + @Override + public void setServer(String server) { + this.server = server; + } + + @Override + public String getSignatureDataURL() { + return this.signatureDataURL; + } + + @Override + public void setSignatureDataURL(String signatureDataURL) { + this.signatureDataURL = signatureDataURL; + } + + @Override + public String ensureSessionID(String url) { + return url; + } +} \ No newline at end of file diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/IAIKHandler.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/IAIKHandler.java new file mode 100644 index 00000000..04338f8b --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/IAIKHandler.java @@ -0,0 +1,312 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +// Imports +import java.io.IOException; +import java.net.URL; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asit.pdfover.gui.bku.BKUHelper; +import at.asit.pdfover.gui.controls.Dialog; +import at.asit.pdfover.gui.controls.Dialog.BUTTONS; +import at.asit.pdfover.gui.controls.Dialog.ICON; +import at.asit.pdfover.gui.utils.Messages; +import at.asit.pdfover.gui.workflow.states.MobileBKUState; +import at.asit.pdfover.signator.SLResponse; + +/** + * + */ +public class IAIKHandler extends MobileBKUHandler { + /** + * SLF4J Logger instance + **/ + private static final Logger log = LoggerFactory + .getLogger(IAIKHandler.class); + + Shell shell; + + /** + * Constructor + * @param state the MobileBKUState + * @param shell the Shell + */ + public IAIKHandler(MobileBKUState state, Shell shell) { + super(state); + this.shell = shell; + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleSLRequestResponse(java.lang.String) + */ + @Override + public void handleSLRequestResponse(String responseData) throws Exception { + IAIKStatus status = getStatus(); + + // Extract infos: + String credentialURL = MobileBKUHelper.extractTag(responseData, + "name=\"userCredLogon\" method=\"post\" action=\"", "\""); //$NON-NLS-1$ //$NON-NLS-2$ + URL baseURL = new URL(status.getBaseURL()); + int p = baseURL.getPort(); + String port = ((p != -1) && (p != baseURL.getDefaultPort())) ? ":" + p : ""; //$NON-NLS-1$ //$NON-NLS-2$ + credentialURL = baseURL.getProtocol() + "://" + baseURL.getHost() + port + //$NON-NLS-1$ + (credentialURL.startsWith("/") ? "" : "/") + credentialURL; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + String viewState = MobileBKUHelper.extractTag(responseData, + "id=\"javax.faces.ViewState\" value=\"", "\""); //$NON-NLS-1$ //$NON-NLS-2$ + + String sessionID = credentialURL.substring(credentialURL.indexOf("jsessionid=") + 11); //$NON-NLS-1$ + + log.info("credentialURL: " + credentialURL); //$NON-NLS-1$ + log.info("sessionID: " + sessionID); //$NON-NLS-1$ + log.info("viewState: " + viewState); //$NON-NLS-1$ + + status.setBaseURL(credentialURL); + status.setSessionID(sessionID); + status.setViewState(viewState); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#postCredentials() + */ + @Override + public String postCredentials() throws Exception { + IAIKStatus status = getStatus(); + + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = BKUHelper.getHttpClient(); + + PostMethod post = new PostMethod(status.getBaseURL()); + post.getParams().setContentCharset("utf-8"); //$NON-NLS-1$ + post.addParameter("javax.faces.ViewState", status.getViewState()); //$NON-NLS-1$ + post.addParameter("userCredLogon:phoneNR", status.getPhoneNumber()); //$NON-NLS-1$ + post.addParameter("userCredLogon:pwd", status.getMobilePassword()); //$NON-NLS-1$ + post.addParameter("userCredLogon:logonButton", "userCredLogon:logonButton"); //$NON-NLS-1$ //$NON-NLS-2$ + post.addParameter("javax.faces.partial.ajax", "true"); //$NON-NLS-1$ //$NON-NLS-2$ + post.addParameter("javax.faces.source", "userCredLogon:logonButton"); //$NON-NLS-1$ //$NON-NLS-2$ + post.addParameter("javax.faces.partial.execute", "@all"); //$NON-NLS-1$ //$NON-NLS-2$ + post.addParameter("javax.faces.partial.render", "userCredLogon:errorMessagePanel userCredLogon:errorMessage"); //$NON-NLS-1$ //$NON-NLS-2$ + post.addParameter("userCredLogon", "userCredLogon"); //$NON-NLS-1$ //$NON-NLS-2$ + post.addParameter("userCredLogon:j_idt20_input", "de"); //$NON-NLS-1$ //$NON-NLS-2$ + + return executePost(client, post); +} + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleCredentialsResponse(java.lang.String) + */ + @Override + public void handleCredentialsResponse(String responseData) throws Exception { + IAIKStatus status = getStatus(); + + String refVal = null; + String signatureDataURL = null; + + status.setErrorMessage(null); + + if (!responseData.contains("referenceValueLogon.jsf")) { //$NON-NLS-1$ + // Assume that an error occurred + + String errorMessage; + try { + errorMessage = MobileBKUHelper.extractTag(responseData, ":errorMessage\">", ""); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (Exception e) { + errorMessage = Messages.getString("error.Unexpected"); //$NON-NLS-1$ + } + status.setErrorMessage(errorMessage); + + // force UI again! + status.setMobilePassword(null); + return; + } + + HttpClient client = BKUHelper.getHttpClient(); + + String redirectURL = status.getBaseURL().substring(0, + status.getBaseURL().lastIndexOf('/', + status.getBaseURL().lastIndexOf('/') - 1) + 1); //Cut off last directory + redirectURL += MobileBKUHelper.extractTag(responseData, + "redirection_url\":\"", "\""); //$NON-NLS-1$ //$NON-NLS-2$ + redirectURL = status.ensureSessionID(redirectURL); + + responseData = getRedirect(client, redirectURL); + + refVal = MobileBKUHelper.extractTag(responseData, + "id=\"j_idt6:refValue\" class=\"strong\">", "", ""); //$NON-NLS-1$ //$NON-NLS-2$ + getStatus().setErrorMessage(errorMessage); + } catch (Exception e) { + // Assume that wrong TAN was entered too many times + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + Dialog dialog = new Dialog(IAIKHandler.this.shell, Messages.getString("common.warning"), //$NON-NLS-1$ + Messages.getString("mobileBKU.tan_tries_exceeded"), //$NON-NLS-1$ + BUTTONS.OK_CANCEL, ICON.QUESTION); + if (dialog.open() == SWT.CANCEL) { + // Go back to BKU Selection + getStatus().setTanTries(-1); + } else { + // Start signature process over + getStatus().setTanTries(-2); + } + } + }); + } + } + } + + @Override + public IAIKStatus getStatus() { + return (IAIKStatus) getState().getStatus(); + } + + private String getRedirect(HttpClient client, String redirectURL) throws HttpException, IOException { + redirectURL = getStatus().ensureSessionID(redirectURL); + log.debug("Sending get request to URL " + redirectURL); //$NON-NLS-1$ + + GetMethod get = new GetMethod(redirectURL); + int returnCode = client.executeMethod(get); + if (returnCode != HttpStatus.SC_OK) { + throw new HttpException(HttpStatus.getStatusText(returnCode)); + } + String responseData = get.getResponseBodyAsString(); + log.debug("Response: " + responseData); //$NON-NLS-1$ + return responseData; + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.bku.mobile.MobileBKUHandler#useBase64Request() + */ + @Override + protected boolean useBase64Request() { + return false; + } +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/IAIKStatus.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/IAIKStatus.java new file mode 100644 index 00000000..3f354f94 --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/IAIKStatus.java @@ -0,0 +1,80 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +// Imports +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asit.pdfover.gui.workflow.config.ConfigProvider; + +/** + * IAIK MobileBKUStatus implementation + */ +public class IAIKStatus extends AbstractMobileBKUStatusImpl { + /** + * SLF4J Logger instance + **/ + @SuppressWarnings("unused") + private static final Logger log = LoggerFactory.getLogger(IAIKStatus.class); + + /** Maximum number of TAN tries */ + public static final int MOBILE_MAX_TAN_TRIES = 3; + + private String viewState; + + /** + * Constructor + * @param provider the ConfigProvider + */ + public IAIKStatus(ConfigProvider provider) { + setPhoneNumber(provider.getDefaultMobileNumber()); + setMobilePassword(provider.getDefaultMobilePassword()); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUStatus#getMaxTanTries() + */ + @Override + public int getMaxTanTries() { + return MOBILE_MAX_TAN_TRIES; + } + + /** + * @return the viewstate + */ + public String getViewState() { + return this.viewState; + } + + /** + * @param viewState + * the viewState to set + */ + public void setViewState(String viewState) { + this.viewState = viewState; + } + + @Override + public String ensureSessionID(String url) + { + if (url.contains("jsessionid=")) //$NON-NLS-1$ + return url; + + url += ";jsessionid=" + getSessionID(); //$NON-NLS-1$ + return url; + } +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUHandler.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUHandler.java new file mode 100644 index 00000000..3c2609a7 --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUHandler.java @@ -0,0 +1,264 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.apache.commons.httpclient.methods.multipart.StringPart; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asit.pdfover.gui.bku.BKUHelper; +import at.asit.pdfover.gui.utils.FileUploadSource; +import at.asit.pdfover.gui.workflow.states.LocalBKUState; +import at.asit.pdfover.gui.workflow.states.MobileBKUState; +import at.asit.pdfover.signator.SLRequest; +import at.asit.pdfover.signator.SigningState; + +/** + * A mobile BKU Handler + */ +public abstract class MobileBKUHandler { + /** + * SLF4J Logger instance + **/ + static final Logger log = LoggerFactory + .getLogger(MobileBKUHandler.class); + + private MobileBKUState state; + + /** + * Constructor + * @param state the MobileBKUState + */ + public MobileBKUHandler(MobileBKUState state) + { + this.state = state; + } + + /** + * Post the SL request + * @param mobileBKUUrl mobile BKU URL + * @param request SLRequest + * @return the response + * @throws IOException IO error + */ + public String postSLRequest(String mobileBKUUrl, SLRequest request) throws IOException { + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = BKUHelper.getHttpClient(); + + PostMethod post = new PostMethod(mobileBKUUrl); + String sl_request; + if (request.getSignatureData() != null) { + if (useBase64Request()) + { + sl_request = request.getBase64Request(); + post.addParameter("XMLRequest", sl_request); //$NON-NLS-1$ + } else { + sl_request = request.getFileUploadRequest(); + StringPart xmlpart = new StringPart( + "XMLRequest", sl_request, "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$ + + FilePart filepart = new FilePart("fileupload", //$NON-NLS-1$ + new FileUploadSource(request.getSignatureData())); + + Part[] parts = { xmlpart, filepart }; + + post.setRequestEntity(new MultipartRequestEntity(parts, post + .getParams())); + } + } else { + sl_request = request.getRequest(); + post.addParameter("XMLRequest", sl_request); //$NON-NLS-1$ + } + log.debug("SL Request: " + sl_request); //$NON-NLS-1$ + + getState().getStatus().setBaseURL( + MobileBKUHelper.stripQueryString(mobileBKUUrl)); + + return executePost(client, post); + } + + /** + * Handle the response to the SL request post + * @param responseData response data + * @throws Exception Error during handling + */ + public abstract void handleSLRequestResponse(String responseData) throws Exception; + + + /** + * Post the credentials + * @return the response + * @throws Exception Error during posting + */ + public abstract String postCredentials() throws Exception; + + /** + * Handle the response to credentials post + * @param responseData response data + * @throws Exception Error during handling + */ + public abstract void handleCredentialsResponse(String responseData) throws Exception; + + /** + * Post the TAN + * @return the response + * @throws Exception Error during posting + */ + public abstract String postTAN() throws Exception; + + /** + * Handle the response to TAN post + * @param responseData response data + * @throws Exception Error during handling + */ + public abstract void handleTANResponse(String responseData) throws Exception; + + /** + * Get the MobileBKUState + * @return the MobileBKUState + */ + protected MobileBKUState getState() { + return this.state; + } + + /** + * Get the MobileBKUStatus + * @return the MobileBKUStatus + */ + protected MobileBKUStatus getStatus() { + return this.state.getStatus(); + } + + /** + * Get the SigningState + * @return the SigningState + */ + protected SigningState getSigningState() { + return getState().getSigningState(); + } + + /** + * Whether to use a Base64 request + * @return true if base64 request shall be used + */ + protected abstract boolean useBase64Request(); + + /** + * Execute a post to the mobile BKU, following redirects + * @param client the HttpClient + * @param post the PostMethod + * @return the response + * @throws IOException IO error + */ + protected String executePost(HttpClient client, PostMethod post) throws IOException { + if (log.isDebugEnabled()) { + String req; + if (post.getRequestEntity().getContentLength() < 1024) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + post.getRequestEntity().writeRequest(os); + req = os.toString(); + if (req.contains("passwort=")) //$NON-NLS-1$ + req = req.replaceAll("passwort=[^&]*", "passwort=******"); //$NON-NLS-1$ //$NON-NLS-2$ + if (req.contains(":pwd=")) //$NON-NLS-1$ + req = req.replaceAll(":pwd=[^&]*", ":pwd=******"); //$NON-NLS-1$ //$NON-NLS-2$ + os.close(); + } else { + req = post.getRequestEntity().getContentLength() + " bytes"; //$NON-NLS-1$ + } + log.debug("Posting to " + post.getURI() + ": " + req); //$NON-NLS-1$ //$NON-NLS-2$ + } + int returnCode = client.executeMethod(post); + + String redirectLocation = null; + + GetMethod get = null; + + String responseData = null; + + String server = null; + + // Follow redirects + do { + // check return code + if (returnCode == HttpStatus.SC_MOVED_TEMPORARILY || + returnCode == HttpStatus.SC_MOVED_PERMANENTLY) { + + Header locationHeader = post.getResponseHeader("location"); //$NON-NLS-1$ + if (locationHeader != null) { + redirectLocation = locationHeader.getValue(); + } else { + throw new IOException( + "Got HTTP 302 but no location to follow!"); //$NON-NLS-1$ + } + } else if (returnCode == HttpStatus.SC_OK) { + if (get != null) { + responseData = get.getResponseBodyAsString(); + Header serverHeader = get.getResponseHeader( + LocalBKUState.BKU_RESPONSE_HEADER_SERVER); + if (serverHeader != null) + server = serverHeader.getValue(); + } else { + responseData = post.getResponseBodyAsString(); + + Header serverHeader = post.getResponseHeader( + LocalBKUState.BKU_RESPONSE_HEADER_SERVER); + if (serverHeader != null) + server = serverHeader.getValue(); + } + redirectLocation = null; + String p = "]*http-equiv=\"refresh\" [^>]*content=\"([^\"]*)\""; //$NON-NLS-1$ + Pattern pat = Pattern.compile(p); + Matcher m = pat.matcher(responseData); + if (m.find()) { + String content = m.group(1); + int start = content.indexOf("URL=") +9; //$NON-NLS-1$ + redirectLocation = content.substring(start, content.length() - 5); + } + } else { + throw new HttpException( + HttpStatus.getStatusText(returnCode)); + } + + if (redirectLocation != null) { + redirectLocation = getStatus().ensureSessionID(redirectLocation); + log.debug("Redirected to " + redirectLocation); //$NON-NLS-1$ + get = new GetMethod(redirectLocation); + get.setFollowRedirects(true); + returnCode = client.executeMethod(get); + } + } while (redirectLocation != null); + + getStatus().setServer(server); + if (server != null) + log.info("Server: " + server); //$NON-NLS-1$ + + return responseData; + } +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUHelper.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUHelper.java new file mode 100644 index 00000000..5e96366f --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUHelper.java @@ -0,0 +1,158 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +// Imports +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.httpclient.protocol.Protocol; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asit.pdfover.gui.exceptions.InvalidNumberException; +import at.asit.pdfover.gui.exceptions.InvalidPasswordException; +import at.asit.pdfover.gui.exceptions.PasswordTooLongException; +import at.asit.pdfover.gui.exceptions.PasswordTooShortException; + +/** + * + */ +public class MobileBKUHelper { + /** + * SLF4J Logger instance + **/ + private static final Logger log = LoggerFactory + .getLogger(MobileBKUHelper.class); + + /** + * Regular expression for mobile phone numbers: this allows the entry of + * mobile numbers in the following formats: + * + * +(countryCode)99999999999 00(countryCode)99999999999 099999999999 + * 1030199999999999 (A-Trust Test bku) + */ + private static final String NUMBER_REGEX = "^((\\+[\\d]{2})|(00[\\d]{2})|(0)|(10301))([1-9][\\d]+)$"; //$NON-NLS-1$ + + /** + * Extracts a substring from data starting after start and ending with end + * + * @param data + * the whole data string + * @param start + * the start marker + * @param end + * the end marker + * @return the substring + * @throws Exception + */ + public static String extractTag(String data, String start, String end) + throws Exception { + int startidx = data.indexOf(start); + if (startidx > 0) { + startidx = startidx + start.length(); + int endidx = data.indexOf(end, startidx); + if (endidx > startidx) { + return data.substring(startidx, endidx); + } + log.error("extracting Tag: end tag not valid!: " + start + " ... " + end); //$NON-NLS-1$//$NON-NLS-2$ + throw new Exception("end tag not available!"); //$NON-NLS-1$ + } + log.error("extracting Tag: start tag not valid!: " + start + " ... " + end); //$NON-NLS-1$//$NON-NLS-2$ + throw new Exception("start tag not available!"); //$NON-NLS-1$ + } + + /** + * Validates the Mobile phone number + * + * @param number + * @return the normalized Phone number + * @throws InvalidNumberException + */ + public static String normalizeMobileNumber(String number) + throws InvalidNumberException { + // Verify number and normalize + + // Compile and use regular expression + Pattern pattern = Pattern.compile(NUMBER_REGEX); + Matcher matcher = pattern.matcher(number); + + if (!matcher.find()) { + throw new InvalidNumberException(); + } + + if (matcher.groupCount() != 6) { + throw new InvalidNumberException(); + } + + String countryCode = matcher.group(1); + + String normalNumber = matcher.group(6); + + if (countryCode.equals("10301")) { //$NON-NLS-1$ + // A-Trust Testnumber! Don't change + return number; + } + + countryCode = countryCode.replace("00", "+"); //$NON-NLS-1$ //$NON-NLS-2$ + + if (countryCode.equals("0")) { //$NON-NLS-1$ + countryCode = "+43"; //$NON-NLS-1$ + } + + return countryCode + normalNumber; + } + + /** + * Validate given Password for Mobile BKU + * + * @param password + * @throws InvalidPasswordException + */ + public static void validatePassword(String password) + throws InvalidPasswordException { + if (password.length() < 6 || password.length() > 20) { + if (password.length() < 6) { + throw new PasswordTooShortException(); + } + throw new PasswordTooLongException(); + } + } + + /** + * Removes file extension from URL + * + * @param query + * the url string + * @return the stripped url + */ + public static String stripQueryString(String query) { + int pathidx = query.lastIndexOf('/'); + if (pathidx > 0) { + return query.substring(0, pathidx); + } + return query; + } + + /** + * Register our TrustedSocketFactory for https connections + */ + @SuppressWarnings("deprecation") + public static void registerTrustedSocketFactory() { + Protocol.registerProtocol("https", //$NON-NLS-1$ + new Protocol("https", new TrustedSocketFactory(), 443)); //$NON-NLS-1$ + } +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUStatus.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUStatus.java new file mode 100644 index 00000000..321faac5 --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUStatus.java @@ -0,0 +1,140 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +/** + * + */ +public interface MobileBKUStatus { + /** + * @return the identification_url + */ + public String getSessionID(); + + /** + * @param sessionID the identification_url to set + */ + public void setSessionID(String sessionID); + + /** + * @return the phoneNumber + */ + public String getPhoneNumber(); + + /** + * @param phoneNumber the phoneNumber to set + */ + public void setPhoneNumber(String phoneNumber); + + /** + * @return the mobilePassword + */ + public String getMobilePassword(); + + /** + * @param mobilePassword the mobilePassword to set + */ + public void setMobilePassword(String mobilePassword); + + /** + * @return the reference value + */ + public String getRefVal(); + + /** + * @param refVal the reference value to set + */ + public void setRefVal(String refVal); + + /** + * @return the tan + */ + public String getTan(); + + /** + * @param tan the tan to set + */ + public void setTan(String tan); + + /** + * Get maximum number of TAN tries + * @return the maximum number of TAN tries + */ + public int getMaxTanTries(); + + /** + * Get number of TAN tries left + * @return the number of TAN tries left + */ + public int getTanTries(); + + /** + * Set number of TAN tries left + * @param tries the number of TAN tries left + */ + public void setTanTries(int tries); + + /** + * @return the errorMessage + */ + public String getErrorMessage(); + + /** + * @param errorMessage the errorMessage to set + */ + public void setErrorMessage(String errorMessage); + + /** + * @return the baseURL + */ + public String getBaseURL(); + + /** + * @param baseURL + */ + public void setBaseURL(String baseURL); + + /** + * Return the SL request server + * @return the SL request server + */ + public String getServer(); + + /** + * Set the SL request server + * @param server the SL request server + */ + public void setServer(String server); + + /** + * Get the signature data URL + * @return the signature data URL + */ + public String getSignatureDataURL(); + + /** + * Set the signature data URL + * @param signatureDataURL the signature data URL + */ + public void setSignatureDataURL(String signatureDataURL); + + /** + * Ensure that given URL contains a session ID (if necessary) + * @param url URL to check for session ID + * @return resulting URL + */ + public String ensureSessionID(String url); +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUs.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUs.java new file mode 100644 index 00000000..e0c890da --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/MobileBKUs.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +/** + * Available mobile BKUs + */ +public enum MobileBKUs { + /** A-Trust BKU */ + A_TRUST, + + /** IAIK */ + IAIK +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/SimpleXMLTrustManager.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/SimpleXMLTrustManager.java new file mode 100644 index 00000000..bceb59fb --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/SimpleXMLTrustManager.java @@ -0,0 +1,225 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +// Imports +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import at.asit.pdfover.gui.Constants; + +/** + * + */ +public class SimpleXMLTrustManager implements X509TrustManager { + /** + * SLF4J Logger instance + **/ + private static final Logger log = LoggerFactory + .getLogger(SimpleXMLTrustManager.class); + + /* + * The default X509TrustManager returned by SunX509. We'll delegate + * decisions to it, and fall back to the logic in this class if the default + * X509TrustManager doesn't trust it. + */ + X509TrustManager sunJSSEX509TrustManager; + + /** + * Trust Manager for A-Trust Certificates + */ + X509TrustManager atrustTrustManager; + + /** + * Constructs the TrustManager + * + * @throws Exception + */ + public SimpleXMLTrustManager() throws Exception { + // create a "default" JSSE X509TrustManager. + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); //$NON-NLS-1$ + tmf.init((KeyStore) null); + + TrustManager tms[] = tmf.getTrustManagers(); + + /* + * Iterate over the returned trustmanagers, look for an instance of + * X509TrustManager. If found, use that as our "default" trust manager. + */ + for (int i = 0; i < tms.length; i++) { + if (tms[i] instanceof X509TrustManager) { + this.sunJSSEX509TrustManager = (X509TrustManager) tms[i]; + break; + } + } + + /* + * A-Trust Certificates + */ + + KeyStore myKeyStore = KeyStore.getInstance(KeyStore + .getDefaultType()); + + myKeyStore.load(null); + + Document doc = DocumentBuilderFactory.newInstance() + .newDocumentBuilder() + .parse(this.getClass().getResourceAsStream(Constants.RES_CERT_LIST)); + + Node certificates = doc.getFirstChild(); + + if (!certificates.getNodeName().equals("certificates")) { //$NON-NLS-1$ + throw new Exception( + "Used certificates xml is invalid! no certificates node"); //$NON-NLS-1$ + } + + NodeList certificateList = certificates.getChildNodes(); + + for (int i = 0; i < certificateList.getLength(); i++) { + try { + + Node certificateNode = certificateList.item(i); + + if (certificateNode.getNodeName().equals("#text")) { //$NON-NLS-1$ + continue; // Ignore dummy text node .. + } + + if (!certificateNode.getNodeName().equals("certificate")) { //$NON-NLS-1$ + log.warn("Ignoring XML node: " + certificateNode.getNodeName()); //$NON-NLS-1$ + continue; + } + + String certResource = Constants.RES_CERT_PATH + certificateNode.getTextContent(); + + X509Certificate cert = (X509Certificate) CertificateFactory + .getInstance("X509"). //$NON-NLS-1$ + generateCertificate( + this.getClass().getResourceAsStream( + certResource)); + + myKeyStore.setCertificateEntry(certificateNode.getTextContent(), cert); + + log.debug("Loaded certificate : " + certResource); //$NON-NLS-1$ + + } catch (Exception ex) { + log.error("Failed to load certificate [" + "]", ex); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + tmf.init(myKeyStore); + + tms = tmf.getTrustManagers(); + + /* + * Iterate over the returned trustmanagers, look for an instance of + * X509TrustManager. If found, use that as our "default" trust manager. + */ + for (int i = 0; i < tms.length; i++) { + if (tms[i] instanceof X509TrustManager) { + this.atrustTrustManager = (X509TrustManager) tms[i]; + break; + } + } + + if (this.sunJSSEX509TrustManager != null + && this.atrustTrustManager != null) { + return; + } + + /* + * Find some other way to initialize, or else we have to fail the + * constructor. + */ + throw new Exception("Couldn't initialize ASITTrustManager"); //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * + * @see + * javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert. + * X509Certificate[], java.lang.String) + */ + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + try { + this.atrustTrustManager.checkServerTrusted(arg0, arg1); + } catch (CertificateException ex) { + try { + this.sunJSSEX509TrustManager.checkClientTrusted(arg0, arg1); + } catch (CertificateException ex2) { + log.info("checkClientTrusted: ", ex2); //$NON-NLS-1$ + throw ex2; + } + } + } + + /* + * (non-Javadoc) + * + * @see + * javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert. + * X509Certificate[], java.lang.String) + */ + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + try { + this.atrustTrustManager.checkServerTrusted(arg0, arg1); + } catch (CertificateException ex) { + try { + this.sunJSSEX509TrustManager.checkServerTrusted(arg0, arg1); + } catch (CertificateException ex2) { + log.info("checkServerTrusted: ", ex2); //$NON-NLS-1$ + throw ex2; + } + } + } + + /* + * (non-Javadoc) + * + * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() + */ + @Override + public X509Certificate[] getAcceptedIssuers() { + + X509Certificate[] default_certs = this.sunJSSEX509TrustManager.getAcceptedIssuers(); + + X509Certificate[] atrust_certs = this.atrustTrustManager.getAcceptedIssuers(); + + X509Certificate[] all_certs = Arrays.copyOf(default_certs, default_certs.length + atrust_certs.length); + System.arraycopy(atrust_certs, 0, all_certs, default_certs.length, atrust_certs.length); + return all_certs; + } + +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/TrustedSocketFactory.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/TrustedSocketFactory.java new file mode 100644 index 00000000..4fa71703 --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/mobile/TrustedSocketFactory.java @@ -0,0 +1,192 @@ +/* + * Copyright 2012 by A-SIT, Secure Information Technology Center Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ +package at.asit.pdfover.gui.bku.mobile; + +// Imports +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asit.pdfover.gui.utils.Messages; + +/** + * + */ +public class TrustedSocketFactory implements SecureProtocolSocketFactory { + /** + * SLF4J Logger instance + **/ + private static final Logger log = LoggerFactory + .getLogger(TrustedSocketFactory.class); + + private static final String ENABLED_CS[] = { + "TLS_RSA_WITH_AES_128_CBC_SHA", //$NON-NLS-1$ + "SSL_RSA_WITH_RC4_128_SHA", //$NON-NLS-1$ + "SSL_RSA_WITH_3DES_EDE_CBC_SHA", //$NON-NLS-1$ + "SSL_RSA_WITH_RC4_128_MD5" //$NON-NLS-1$ + }; + + private static SSLSocketFactory getFactory() throws NoSuchAlgorithmException, + KeyManagementException, Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); //$NON-NLS-1$ + sslContext.init(null, new TrustManager[] { new SimpleXMLTrustManager() }, + new java.security.SecureRandom()); + + return sslContext.getSocketFactory(); + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket + * (java.lang.String, int) + */ + @Override + public Socket createSocket(String host, int port) throws IOException, + UnknownHostException { + try { + SSLSocket sslSocket = (SSLSocket) getFactory().createSocket(host, + port); + sslSocket.setEnabledCipherSuites(ENABLED_CS); + return sslSocket; + } catch (Exception ex) { + log.error("TrustedSocketFactory: ", ex); //$NON-NLS-1$ + if (ex instanceof IOException) { + throw (IOException) ex; + } else if (ex instanceof UnknownHostException) { + throw (UnknownHostException) ex; + } else { + throw new IOException( + Messages.getString("TrustedSocketFactory.FailedToCreateSecureConnection"), ex); //$NON-NLS-1$ + } + } + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket + * (java.lang.String, int, java.net.InetAddress, int) + */ + @Override + public Socket createSocket(String host, int port, InetAddress clientHost, + int clientPort) throws IOException, UnknownHostException { + try { + SSLSocket sslSocket = (SSLSocket) getFactory().createSocket(host, + port, clientHost, clientPort); + sslSocket.setEnabledCipherSuites(ENABLED_CS); + return sslSocket; + } catch (Exception ex) { + log.error("TrustedSocketFactory: ", ex); //$NON-NLS-1$ + if (ex instanceof IOException) { + throw (IOException) ex; + } else if (ex instanceof UnknownHostException) { + throw (UnknownHostException) ex; + } else { + throw new IOException( + Messages.getString("TrustedSocketFactory.FailedToCreateSecureConnection"), ex); //$NON-NLS-1$ + } + } + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket + * (java.lang.String, int, java.net.InetAddress, int, + * org.apache.commons.httpclient.params.HttpConnectionParams) + */ + @Override + public Socket createSocket(String host, int port, InetAddress clientHost, + int clientPort, HttpConnectionParams params) throws IOException, + UnknownHostException, ConnectTimeoutException { + try { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); //$NON-NLS-1$ + } + int timeout = params.getConnectionTimeout(); + SSLSocket sslSocket = null; + + SSLSocketFactory socketfactory = getFactory(); + if (timeout == 0) { + sslSocket = (SSLSocket) socketfactory.createSocket(host, port, clientHost, + clientPort); + } else { + sslSocket = (SSLSocket) socketfactory.createSocket(); + SocketAddress localaddr = new InetSocketAddress(clientHost, + clientPort); + SocketAddress remoteaddr = new InetSocketAddress(host, port); + sslSocket.bind(localaddr); + sslSocket.connect(remoteaddr, timeout); + } + sslSocket.setEnabledCipherSuites(ENABLED_CS); + return sslSocket; + } catch (Exception ex) { + log.error("TrustedSocketFactory: ", ex); //$NON-NLS-1$ + if (ex instanceof IOException) { + throw (IOException) ex; + } else if (ex instanceof UnknownHostException) { + throw (UnknownHostException) ex; + } else { + throw new IOException( + Messages.getString("TrustedSocketFactory.FailedToCreateSecureConnection"), ex); //$NON-NLS-1$ + } + } + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory#createSocket(java.net.Socket, java.lang.String, int, boolean) + */ + @Override + public Socket createSocket(Socket socket, String host, int port, + boolean autoClose) throws IOException, UnknownHostException { + try { + SSLSocket sslSocket = (SSLSocket) getFactory().createSocket(socket, host, port, autoClose); + sslSocket.setEnabledCipherSuites(ENABLED_CS); + return sslSocket; + } catch (Exception ex) { + log.error("TrustedSocketFactory: ", ex); //$NON-NLS-1$ + if (ex instanceof IOException) { + throw (IOException) ex; + } else if (ex instanceof UnknownHostException) { + throw (UnknownHostException) ex; + } else { + throw new IOException( + Messages.getString("TrustedSocketFactory.FailedToCreateSecureConnection"), ex); //$NON-NLS-1$ + } + } + } + +} -- cgit v1.2.3