From e2ab585fc4cfc165dc02ea9142f33dd308979e49 Mon Sep 17 00:00:00 2001 From: Jakob Heher Date: Mon, 3 Oct 2022 17:36:36 +0200 Subject: start untangling BKU handler from GUI logic --- .../pdfover/gui/bku/OLDmobile/ATrustHandler.java | 793 +++++++++++++++++++++ .../pdfover/gui/bku/OLDmobile/ATrustStatus.java | 68 ++ .../pdfover/gui/bku/OLDmobile/MobileBKUHelper.java | 318 +++++++++ .../asit/pdfover/gui/bku/OLDmobile/MobileBKUs.java | 27 + .../gui/bku/OLDmobile/SimpleXMLTrustManager.java | 220 ++++++ .../gui/bku/OLDmobile/TrustedSocketFactory.java | 191 +++++ 6 files changed, 1617 insertions(+) create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/ATrustHandler.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/ATrustStatus.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/MobileBKUHelper.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/MobileBKUs.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/SimpleXMLTrustManager.java create mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/TrustedSocketFactory.java (limited to 'pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile') diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/ATrustHandler.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/ATrustHandler.java new file mode 100644 index 00000000..2e69e779 --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/ATrustHandler.java @@ -0,0 +1,793 @@ +/* + * 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.OLDmobile; + +// Imports +import java.awt.Desktop; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +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.apache.commons.io.IOUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.program.Program; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import at.asit.pdfover.commons.Constants; +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.exceptions.ATrustConnectionException; +import at.asit.pdfover.gui.utils.FileUploadSource; +import at.asit.pdfover.commons.Messages; +import at.asit.pdfover.gui.workflow.states.LocalBKUState; +import at.asit.pdfover.gui.workflow.states.MobileBKUState; +import at.asit.pdfover.signer.pdfas.PdfAs4SLRequest; +import at.asit.pdfover.signer.pdfas.PdfAs4SigningState; + +/** + * A-Trust mobile BKU handler + */ +public class ATrustHandler { + public final MobileBKUState state; + public final Shell shell; + + /** + * @param state + * @param shell + */ + public ATrustHandler(MobileBKUState state, Shell shell) { + this.state = state; + this.shell = shell; + } + + /** + * SLF4J Logger instance + **/ + static final Logger log = LoggerFactory.getLogger(ATrustHandler.class); + + private static boolean expiryNoticeDisplayed = false; + + private static final String ACTIVATION_URL = "https://www.handy-signatur.at/"; + + /** + * Get the MobileBKUStatus + * @return the MobileBKUStatus + */ + protected ATrustStatus getStatus() { + return this.state.status; + } + + /** + * Get the SigningState + * @return the SigningState + */ + protected PdfAs4SigningState getSigningState() { + return state.getSigningState(); + } + + /** + * 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=")) + req = req.replaceAll("passwort=[^&]*", "passwort=******"); + if (req.contains(":pwd=")) + req = req.replaceAll(":pwd=[^&]*", ":pwd=******"); + os.close(); + } else { + req = post.getRequestEntity().getContentLength() + " bytes"; + } + log.debug("Posting to " + post.getURI() + ": " + req); + } + 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"); + if (locationHeader != null) { + redirectLocation = locationHeader.getValue(); + } else { + throw new IOException( + "Got HTTP 302 but no location to follow!"); + } + } 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=\"([^\"]*)\""; + Pattern pat = Pattern.compile(p); + Matcher m = pat.matcher(responseData); + if (m.find()) { + String content = m.group(1); + int start = content.indexOf("URL="); + if (start != -1) { + start += 9; + redirectLocation = content.substring(start, content.length() - 5); + } + } + } else { + throw new HttpException( + HttpStatus.getStatusText(returnCode)); + } + + if (redirectLocation != null) { + redirectLocation = MobileBKUHelper.getQualifiedURL(redirectLocation, new URL(post.getURI().toString())); + log.debug("Redirected to " + redirectLocation); + get = new GetMethod(redirectLocation); + get.setFollowRedirects(true); + returnCode = client.executeMethod(get); + } + } while (redirectLocation != null); + + getStatus().server = server; + if (server != null) + log.debug("Server: " + server); + + return responseData; + } + + /** + * Execute a get from the mobile BKU, following redirects + * @param client the HttpClient + * @param get the GetMethod + * @return the response + * @throws IOException IO error + */ + protected String executeGet(HttpClient client, GetMethod get) throws IOException { + log.debug("Getting " + get.getURI()); + + int returnCode = client.executeMethod(get); + + String redirectLocation = null; + + GetMethod get2 = 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 = get.getResponseHeader("location"); + if (locationHeader != null) { + redirectLocation = locationHeader.getValue(); + } else { + throw new IOException( + "Got HTTP 302 but no location to follow!"); + } + } else if (returnCode == HttpStatus.SC_OK) { + if (get2 != null) { + responseData = get2.getResponseBodyAsString(); + Header serverHeader = get2.getResponseHeader( + LocalBKUState.BKU_RESPONSE_HEADER_SERVER); + if (serverHeader != null) + server = serverHeader.getValue(); + } else { + responseData = get.getResponseBodyAsString(); + + Header serverHeader = get.getResponseHeader( + LocalBKUState.BKU_RESPONSE_HEADER_SERVER); + if (serverHeader != null) + server = serverHeader.getValue(); + } + redirectLocation = null; + String p = "]*http-equiv=\"refresh\" [^>]*content=\"([^\"]*)\""; + Pattern pat = Pattern.compile(p); + Matcher m = pat.matcher(responseData); + if (m.find()) { + String content = m.group(1); + int start = content.indexOf("URL="); + if (start != -1) { + start += 9; + redirectLocation = content.substring(start, content.length() - 5); + } + } + } else { + throw new HttpException( + HttpStatus.getStatusText(returnCode)); + } + + if (redirectLocation != null) { + redirectLocation = MobileBKUHelper.getQualifiedURL(redirectLocation, new URL(get.getURI().toString())); + log.debug("Redirected to " + redirectLocation); + get2 = new GetMethod(redirectLocation); + get2.setFollowRedirects(true); + returnCode = client.executeMethod(get2); + } + } while (redirectLocation != null); + + getStatus().server = server; + if (server != null) + log.debug("Server: " + server); + + return responseData; + } + + /** + * Post the SL request + * @param mobileBKUUrl mobile BKU URL + * @param request SLRequest + * @return the response + * @throws IOException IO error + */ + public String postSLRequest(String mobileBKUUrl, PdfAs4SLRequest request) throws IOException { + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = MobileBKUHelper.getHttpClient(getStatus()); + + PostMethod post = new PostMethod(mobileBKUUrl); + String sl_request; + if (request.signatureData != null) { + sl_request = request.xmlRequest; + StringPart xmlpart = new StringPart( + "XMLRequest", sl_request, "UTF-8"); + + FilePart filepart = new FilePart("fileupload", + new FileUploadSource(request.signatureData), + "application/pdf", "UTF-8"); + + Part[] parts = { xmlpart, filepart }; + + post.setRequestEntity(new MultipartRequestEntity(parts, post + .getParams())); + } else { + sl_request = request.xmlRequest; + post.addParameter("XMLRequest", sl_request); + } + log.trace("SL Request: " + sl_request); + + state.status.baseURL = MobileBKUHelper.stripQueryString(mobileBKUUrl); + + return executePost(client, post); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleSLRequestResponse(java.lang.String) + */ + public void handleSLRequestResponse(String responseData) throws Exception { + ATrustStatus status = getStatus(); + + if (responseData.contains("", ""); + String errorMsg = MobileBKUHelper.extractSubstring(responseData, + "", ""); + throw new Exception("Error from mobile BKU: " + + errorCode + " - " + errorMsg); + } + + // Extract infos: + String sessionID = MobileBKUHelper.extractSubstring(responseData, + "identification.aspx?sid=", "\""); + + String viewState = MobileBKUHelper.extractValueFromTagWithParam( + responseData, "", "id", "__VIEWSTATE", "value"); + + String eventValidation = MobileBKUHelper.extractValueFromTagWithParam( + responseData, "", "id", "__EVENTVALIDATION", "value"); + + String viewstateGenerator = MobileBKUHelper.extractValueFromTagWithParamOptional(responseData, "", "id", "__VIEWSTATEGENERATOR", "value"); + + String dynamicAttrPhonenumber = MobileBKUHelper.getDynamicNameAttribute(responseData, Constants.LABEL_PHONE_NUMBER); + String dynamicAttrPassword = MobileBKUHelper.getDynamicNameAttribute(responseData, Constants.LABEL_SIGN_PASS); + String dynamicAttrButtonId = MobileBKUHelper.getDynamicNameAttribute(responseData, Constants.LABEL_BTN_IDF); + String dynamicAttrTan = MobileBKUHelper.getDynamicNameAttribute(responseData, Constants.LABEL_TAN); + + + log.debug("sessionID: " + sessionID); + log.debug("viewState: " + viewState); + log.debug("eventValidation: " + eventValidation); + + status.sessionID = sessionID; + status.viewState = viewState; + status.eventValidation = eventValidation; + if (viewstateGenerator != null ) { status.viewStateGenerator = viewstateGenerator; } + status.dynAttrPhoneNumber = dynamicAttrPhonenumber; + status.dynAttrPassword = dynamicAttrPassword; + status.dynAttrBtnId = dynamicAttrButtonId; + status.dynAttrTan = dynamicAttrTan; + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#postCredentials() + */ + public String postCredentials() throws IOException { + ATrustStatus status = getStatus(); + + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = MobileBKUHelper.getHttpClient(getStatus()); + + PostMethod post = new PostMethod(status.baseURL + "/identification.aspx?sid=" + status.sessionID); + post.getParams().setContentCharset("utf-8"); + post.addParameter("__VIEWSTATE", status.viewState); + post.addParameter("__VIEWSTATEGENERATOR", status.viewStateGenerator); + post.addParameter("__EVENTVALIDATION", status.eventValidation); + post.addParameter(status.dynAttrPhoneNumber, status.phoneNumber); + post.addParameter(status.dynAttrPassword, status.mobilePassword); + post.addParameter(status.dynAttrBtnId, "Identifizieren"); + + return executePost(client, post); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleCredentialsResponse(java.lang.String) + */ + public void handleCredentialsResponse(final String responseData) throws Exception { + ATrustStatus status = getStatus(); + String viewState = status.viewState; + String eventValidation = status.eventValidation; + String sessionID = status.sessionID; + String refVal = null; + String signatureDataURL = null; + String viewstateGenerator = status.viewStateGenerator; + + status.errorMessage = null; + + final Document responseDocument = Jsoup.parse(responseData); + + if (responseData.contains("ExpiresInfo.aspx?sid=")) { + // Certificate expiration interstitial - skip + if (!expiryNoticeDisplayed) { + Display.getDefault().syncExec(()-> { + Dialog d = new Dialog(ATrustHandler.this.shell, Messages.getString("common.info"), Messages.getString("mobileBKU.certExpiresSoon"), BUTTONS.YES_NO, ICON.WARNING); + if (d.open() == SWT.YES) { + log.debug("Trying to open " + ACTIVATION_URL); + if (Desktop.isDesktopSupported()) { + try { + Desktop.getDesktop().browse(new URI(ACTIVATION_URL)); + return; + } catch (Exception e) { + log.debug("Error opening URL", e); + } + } + log.info("SWT Desktop is not supported on this platform"); + Program.launch(ACTIVATION_URL); + } + }); + expiryNoticeDisplayed = true; + } + + String t_sessionID = MobileBKUHelper.extractSubstring(responseData, "ExpiresInfo.aspx?sid=", "\""); + String t_viewState = MobileBKUHelper.extractValueFromTagWithParam(responseData, "", "id", "__VIEWSTATE", "value"); + String t_eventValidation = MobileBKUHelper.extractValueFromTagWithParam(responseData, "", "id", "__EVENTVALIDATION", "value"); + + // Post again to skip + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = MobileBKUHelper.getHttpClient(getStatus()); + + PostMethod post = new PostMethod(status.baseURL + "/ExpiresInfo.aspx?sid=" + t_sessionID); + post.getParams().setContentCharset("utf-8"); + post.addParameter("__VIEWSTATE", t_viewState); + post.addParameter("__EVENTVALIDATION", t_eventValidation); + post.addParameter("Button_Next", "Weiter"); + + handleCredentialsResponse(executePost(client, post)); + return; + } else if (responseData.contains("tanAppInfo.aspx?sid=")) { + // App info interstitial - skip + log.info("Skipping tan app interstitial"); + + String t_sessionID = MobileBKUHelper.extractSubstring(responseData, "tanAppInfo.aspx?sid=", "\""); + String t_viewState = MobileBKUHelper.extractValueFromTagWithParam(responseData, "", "id", "__VIEWSTATE", "value"); + String t_eventValidation = MobileBKUHelper.extractValueFromTagWithParam(responseData, "", "id", "__EVENTVALIDATION", "value"); + + // Post again to skip + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = MobileBKUHelper.getHttpClient(getStatus()); + + PostMethod post = new PostMethod(status.baseURL + "/tanAppInfo.aspx?sid=" + t_sessionID); + post.getParams().setContentCharset("utf-8"); + post.addParameter("__VIEWSTATE", t_viewState); + post.addParameter("__EVENTVALIDATION", t_eventValidation); + post.addParameter("NextBtn", "Weiter"); + + handleCredentialsResponse(executePost(client, post)); + return; + } + + if (responseData.contains("signature.aspx?sid=")) { + // credentials ok! TAN entry + state.rememberCredentialsIfNecessary(status.phoneNumber, status.mobilePassword); + log.debug("Credentials accepted - TAN required"); + sessionID = MobileBKUHelper.extractSubstring(responseData, "signature.aspx?sid=", "\""); + viewState = MobileBKUHelper.extractValueFromTagWithParam(responseData, "", "id", "__VIEWSTATE", "value"); + eventValidation = MobileBKUHelper.extractValueFromTagWithParam(responseData, "", "id", "__EVENTVALIDATION", "value"); + refVal = MobileBKUHelper.extractSubstring(responseData, "id='vergleichswert'>Vergleichswert:", ""); + signatureDataURL = status.baseURL + "/ShowSigobj.aspx" + + MobileBKUHelper.extractSubstring(responseData, "ShowSigobj.aspx", "'"); + try { + String qrCode = MobileBKUHelper.extractValueFromTagWithParam(responseData, "img", "class", "qrcode", "src"); + log.debug("QR Code found: " + qrCode); + status.qrCodeURL = qrCode; + } catch (Exception e) { + log.debug("No QR Code found"); + } + try { + String tanTextTan = MobileBKUHelper.extractValueFromTagWithParam(responseData, "label", "id", "label_for_input_tan", "for"); + status.tanField = tanTextTan.equals("input_tan"); + status.dynAttrTan = MobileBKUHelper.getDynamicNameAttribute(responseData, Constants.LABEL_TAN); + status.dynAttrSignButton = MobileBKUHelper.getDynamicNameAttribute(responseData, Constants.LABEL_SIGN_BTN); + } catch (Exception e) { + log.debug("No tan field found"); + } + try { + String tanTextTan = MobileBKUHelper.extractContentFromTagWithParam(responseData, "span", "id", "text_tan"); + status.isAPPTan = !tanTextTan.toLowerCase().contains("sms"); + status.dynAttrTan = MobileBKUHelper.getDynamicNameAttribute(responseData, Constants.LABEL_TAN); + status.dynAttrSignButton = MobileBKUHelper.getDynamicNameAttribute(responseData, Constants.LABEL_SIGN_BTN); + }catch (Exception e) { + log.debug("No text_tan tag"); + } + try { + String webauthnLink = MobileBKUHelper.extractValueFromTagWithParam(responseData, "a", "id", "FidoButton", "href"); + log.info("Webauthn link: {}", webauthnLink); + } catch (Exception e) { + log.info("No webauthnLink"); + } + try { + String webauthnData = MobileBKUHelper.extractValueFromTagWithParam(responseData, "input", "id", "credentialOptions", "value"); + log.info("Fido credential options: {}", webauthnData); + } catch (Exception e) { + log.info("No webauthnData"); + } + + } else if (responseData.contains("sl:InfoboxReadResponse")) { + // credentials ok! InfoboxReadResponse + state.rememberCredentialsIfNecessary(status.phoneNumber, status.mobilePassword); + log.debug("Credentials accepted - Response given"); + getSigningState().signatureResponse = responseData; + return; + } else if (responseData.contains("undecided.aspx?sid=")) { + // skip intermediate page + log.debug("Page Undecided"); + getSigningState().signatureResponse = responseData; + status.errorMessage = "waiting..."; // TODO: this looks incorrect...? + return; + }else { + // error page + + // force UI again! + state.clearRememberedPassword(); + // extract error text! + try { + String errorMessage = MobileBKUHelper.extractContentFromTagWithParam(responseData, "span", "id", "Label1"); + if (errorMessage.startsWith("Fehler: ")) + errorMessage = errorMessage.substring(8); + status.errorMessage = errorMessage.strip(); + } catch (Exception e) { + log.error("Failed to get credentials error message", e); + String msg = null; + try + { + msg = MobileBKUHelper.extractSubstring(responseData, "", "") + ": " + + MobileBKUHelper.extractSubstring(responseData, "", ""); + } catch (Exception e2) { + log.error("Failed to get credentials error code", e2); + msg = Messages.getString("error.Unexpected"); + } + status.errorMessage = msg.strip(); + } + } + + log.debug("sessionID: " + sessionID); + log.debug("Vergleichswert: " + refVal); + log.debug("viewState: " + viewState); + log.debug("eventValidation: " + eventValidation); + log.debug("signatureDataURL: " + signatureDataURL); + + status.sessionID = sessionID; + status.refVal = refVal; + status.viewState = viewState; + status.eventValidation = eventValidation; + status.signatureDataURL = signatureDataURL; + status.viewStateGenerator = viewstateGenerator; + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#postTAN() + */ + public String postTAN() throws IOException { + ATrustStatus status = getStatus(); + + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = MobileBKUHelper.getHttpClient(getStatus()); + + PostMethod post = new PostMethod(status.baseURL + + "/signature.aspx?sid=" + status.sessionID); + post.getParams().setContentCharset("utf-8"); + post.addParameter("__VIEWSTATE", status.viewState); + post.addParameter( + "__EVENTVALIDATION", status.eventValidation); + post.addParameter(status.dynAttrTan, status.tan); + post.addParameter(status.dynAttrSignButton, "Signieren"); + post.addParameter("Button1", "Identifizieren"); + + return executePost(client, post); + } + + /* (non-Javadoc) + * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleTANResponse(java.lang.String) + */ + public void handleTANResponse(String responseData) { + getStatus().errorMessage = null; + if (responseData.contains("sl:CreateXMLSignatureResponse xmlns:sl") || + responseData.contains("sl:CreateCMSSignatureResponse xmlns:sl")) { + // success !! + + getSigningState().signatureResponse = responseData; + } else { + try { + String tries = MobileBKUHelper.extractSubstring( + responseData, "Sie haben noch", "Versuch"); + getStatus().tanTries = Integer.parseInt(tries.trim()); + getStatus().errorMessage = "mobileBKU.wrong_tan"; + } catch (Exception e) { + getStatus().tanTries = (getStatus().tanTries - 1); + log.debug("Error parsing TAN response", e); + } + + if (getStatus().tanTries <= 0) { + getStatus().errorMessage = null; + Display.getDefault().syncExec(() -> { + Dialog dialog = new Dialog(ATrustHandler.this.shell, Messages.getString("common.warning"), + Messages.getString("mobileBKU.tan_tries_exceeded"), + BUTTONS.OK_CANCEL, ICON.QUESTION); + + // TODO: THIS IS A COLOSSAL HACK + if (dialog.open() == SWT.CANCEL) { + // Go back to BKU Selection + getStatus().tanTries = -1; + } else { + // Start signature process over + getStatus().tanTries = -2; + } + }); + } + } + } + + /** + * Cancel QR process, request SMS TAN + * @return the response + * @throws IOException Error during posting + */ + public String postSMSRequest() throws IOException { + ATrustStatus status = getStatus(); + + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = MobileBKUHelper.getHttpClient(getStatus()); + + GetMethod get = new GetMethod(status.baseURL + + "/sendsms.aspx?sid=" + status.sessionID); + get.getParams().setContentCharset("utf-8"); + + return executeGet(client, get); + } + + /** + * Get the QR code image + * @return the QR code image as a String + */ + public InputStream getQRCode() { + //TODO: Update HTTPClient here + + ATrustStatus status = getStatus(); + + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = MobileBKUHelper.getHttpClient(getStatus()); + + GetMethod get = new GetMethod(status.baseURL + "/" + status.qrCodeURL); + + try { + log.debug("Getting " + get.getURI()); + int returnCode = client.executeMethod(get); + + if (returnCode != HttpStatus.SC_OK) { + log.error("Error getting QR code"); + return null; + } + + return get.getResponseBodyAsStream(); + } catch (Exception e) { + log.error("Error getting QR code", e); + return null; + } + } + + /** + * Get Signature page after scanning QR code + * @return the response + * @throws IOException Error during get + */ + public String getSignaturePage() throws IOException { + ATrustStatus status = getStatus(); + + MobileBKUHelper.registerTrustedSocketFactory(); + HttpClient client = MobileBKUHelper.getHttpClient(getStatus()); + + //TODO check + //String baseURL = "https://www.a-trust.at/mobile/https-security-layer-request"; + GetMethod get = new GetMethod(status.baseURL + + "/signature.aspx?sid=" + status.sessionID); + + return executeGet(client, get); + } + + /** + * Parse QR code response + * @param responseData + * @return whether a SL response was received + */ + public boolean handleQRResponse(String responseData) { + getStatus().errorMessage = null; + if (responseData.contains("sl:CreateXMLSignatureResponse xmlns:sl") || + responseData.contains("sl:CreateCMSSignatureResponse xmlns:sl")) { + // success !! + + getSigningState().signatureResponse = responseData; + return true; + } + return false; + } + + /* + * (non-Javadoc) + * + */ + public boolean handlePolling() throws ATrustConnectionException { + + ATrustStatus status = getStatus(); + String isReady = null; + Status serverStatus = null; + HttpClient client; + try { + do { + client = MobileBKUHelper.getHttpClient(getStatus()); + String uri = status.baseURL + "/UndecidedPolling.aspx?sid=" + status.sessionID; + GetMethod get = new GetMethod(uri); + + //client.setTimeout(35000); + //client.setConnectionTimeout(35000); + get.addRequestHeader("Accept", "application/json, text/javascript"); + get.addRequestHeader("Connection", "keep-alive"); + get.addRequestHeader("Referer", uri); + + + client.executeMethod(get); + InputStream in = new BufferedInputStream(get.getResponseBodyAsStream()); + + isReady = IOUtils.toString(in, "utf-8"); + serverStatus = new Status(isReady); + + if (serverStatus.isFin()) { + return true; + } else if (serverStatus.isError()) { + log.error("A-Trust returned Error code during polling"); + throw new ATrustConnectionException(); + } + + } while (serverStatus.isWait()); + + if (serverStatus.isFin()) { + return true; + } + //else error + status.errorMessage = "Server reponded ERROR during polling"; + log.error("Server reponded ERROR during polling"); + throw new ATrustConnectionException(); + + } catch (Exception e) { + log.error("handle polling failed" + e.getMessage()); + throw new ATrustConnectionException(); + } + } + + private class Status { + private final boolean fin; + private final boolean error; + private final boolean wait; + + public Status(String status) { + JsonElement jelement = JsonParser.parseString(status.toLowerCase()); + JsonObject jobject = jelement.getAsJsonObject(); + this.fin = jobject.get("fin").getAsBoolean(); + this.error = jobject.get("error").getAsBoolean(); + this.wait = jobject.get("wait").getAsBoolean(); + } + + public boolean isFin() { + return fin; + } + + public boolean isError() { + return error; + } + + public boolean isWait() { + return wait; + } + + + + + } + +} + + diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/ATrustStatus.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/ATrustStatus.java new file mode 100644 index 00000000..22e53a57 --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/ATrustStatus.java @@ -0,0 +1,68 @@ +/* + * 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.OLDmobile; + +// Imports +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asit.pdfover.gui.workflow.config.ConfigurationManager; + +/** + * A-Trust MobileBKUStatus implementation + */ +public class ATrustStatus { + /** + * 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; + + public String sessionID; + public String phoneNumber; + public String mobilePassword; + public String baseURL; + public String refVal; + public String errorMessage; + public String tan; + public String server; + public String signatureDataURL; + public int tanTries = MOBILE_MAX_TAN_TRIES; + public String viewState; + public String eventValidation; + public String qrCodeURL = null; + public boolean tanField = false; + public boolean isAPPTan = false; + public String viewStateGenerator; + public String dynAttrPhoneNumber; + public String dynAttrPassword; + public String dynAttrBtnId; + public String dynAttrTan; + public String dynAttrSignButton; + public boolean isSMSTan = false; + + /** + * Constructor + * @param provider the ConfigProvider + */ + public ATrustStatus(ConfigurationManager provider) { + this.phoneNumber = provider.getDefaultMobileNumber(); + this.mobilePassword = provider.getDefaultMobilePassword(); + } +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/MobileBKUHelper.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/MobileBKUHelper.java new file mode 100644 index 00000000..f258fc05 --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/MobileBKUHelper.java @@ -0,0 +1,318 @@ +/* + * 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.OLDmobile; + +// Imports +import java.net.URL; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.protocol.Protocol; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; +import org.jsoup.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.asit.pdfover.gui.bku.BKUHelper; +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]+)$"; + + /** + * 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 + * not found + */ + public static String extractSubstring(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 substring: end not valid!: " + start + " ... " + end); //// + throw new Exception("End string not available! Mobile BKU site changed?"); + } + log.error("extracting substring: start not valid!: " + start + " ... " + end); //// + throw new Exception("Start string not available! Mobile BKU site changed?"); + } + + /** + * Extracts an XML tag from data with the given param="value" + * + * @param data + * the whole data string + * @param tag + * the tag name (empty string to match all tags) + * @param param + * the parameter to look for + * @param value + * the parameter value to look for + * @return the found tag + * @throws Exception + * not found + */ + public static String extractTagWithParam(String data, String tag, + String param, String value) throws Exception { + String start = '<' + tag; + int startidx, endidx = 0; + while ((startidx = data.indexOf(start, endidx)) != -1) { + endidx = data.indexOf('>', startidx); + if (endidx == -1) { + log.error("extracting tag: unterminated tag! " + tag + " (" + param + "=" + value + ")"); //// + throw new Exception("Tag not found! Mobile BKU site changed?"); + } + String found = data.substring(startidx, endidx + 1); + if (found.contains(param + "='" + value + "'") || + found.contains(param + "=\"" + value + "\"")) + return found; + } + log.info("extracting tag: not found!: " + tag + " (" + param + "='" + value + "')"); //// + throw new Exception("Tag not found! Mobile BKU site changed?"); + } + + /** + * Extracts a parameter value from an XML tag from data with the given param="value" + * + * @param data + * the whole data string + * @param tag + * the tag name (empty string to match all tags) + * @param param + * the parameter to look for + * @param value + * the parameter value to look for + * @param returnparam + * the parameter whose value to return + * @return the found tag + * @throws Exception + * not found + */ + public static String extractValueFromTagWithParam(String data, String tag, + String param, String value, String returnparam) throws Exception { + String found = extractTagWithParam(data, tag, param, value); + int startidx = found.indexOf(returnparam + '='); + if (startidx == -1) { + log.error("extracting tag: param not found! " + tag + " (" + param + "=" + value + ") - " + returnparam); //// + throw new Exception("Tag not found! Mobile BKU site changed?"); + } + startidx += returnparam.length() + 1; + int endidx = found.indexOf(found.charAt(startidx), startidx + 1); + if (endidx == -1) { + log.error("extracting tag: unterminated param value! " + tag + " (" + param + "=" + value + ") - " + returnparam); //// + throw new Exception("Tag not found! Mobile BKU site changed?"); + } + return found.substring(startidx + 1, endidx); + } + + /** + * This method is the same as the non optional method but instead of throwing the exception it returns null + * @return the string or null + */ + public static String extractValueFromTagWithParamOptional(String data, String tag, + String param, String value, String returnparam) { + String str; + try { + str = extractValueFromTagWithParam(data, tag, param, value, returnparam); + } catch (Exception e) { + log.debug("Optional value is not available"); + str = null; + } + return str; + + } + + /** + * Extracts the content from an XML tag from data with the given param="value" + * + * @param data + * the whole data string + * @param tag + * the tag name + * @param param + * the parameter to look for + * @param value + * the parameter value to look for + * @return the found tag's content + * @throws Exception + * not found + */ + public static String extractContentFromTagWithParam(String data, String tag, + String param, String value) throws Exception { + String found = extractTagWithParam(data, tag, param, value); + int startidx = data.indexOf(found) + found.length(); + int endidx = data.indexOf("", startidx); + if (endidx == -1) { + log.error("extracting tag: closing tag not found! " + tag + " (" + param + "=" + value + ")"); //// + throw new Exception("Tag not found! Mobile BKU site changed?"); + } + return data.substring(startidx, endidx); + } + + /** + * Validates the Mobile phone number + * + * @param number + * @return the normalized Phone number + */ + public static String normalizeMobileNumber(String number) { + // Verify number and normalize + + number = number.trim(); + + String numberWithoutWhitespace = number.replaceAll("\\s",""); + // Compile and use regular expression + Pattern pattern = Pattern.compile(NUMBER_REGEX); + Matcher matcher = pattern.matcher(numberWithoutWhitespace); + + if (!matcher.find()) + return number; /* might be an idA username, return unchanged */ + + if (matcher.groupCount() != 6) { + return number; + } + + String countryCode = matcher.group(1); + + String normalNumber = matcher.group(6); + + if (countryCode.equals("10301")) { + // A-Trust Testnumber! Don't change + return numberWithoutWhitespace; + } + + countryCode = countryCode.replace("00", "+"); + + if (countryCode.equals("0")) { + countryCode = "+43"; + } + + return countryCode + normalNumber; + } + + /** + * Validate given Password for Mobile BKU + * + * @param password + * @throws InvalidPasswordException + */ + public static void validatePassword(String password) + throws InvalidPasswordException { + if (password.length() < 5 || password.length() > 200) { + if (password.length() < 6) { + throw new PasswordTooShortException(); + } + throw new PasswordTooLongException(); + } + } + + /** + * Removes file extension from URL + * + * @param url + * the url string + * @return the stripped url + */ + public static String stripQueryString(String url) { + int pathidx = url.lastIndexOf('/'); + if (pathidx > 0) { + return url.substring(0, pathidx); + } + return url; + } + + /** + * Build a fully qualified URL out of a base URL plus a URL fragment + * @param fragment the URL fragment + * @param base the base URL + * @return the fully qualified URL + */ + public static String getQualifiedURL(String fragment, URL base) { + if (fragment.startsWith("http:") || fragment.startsWith("https:")) + return fragment; + int p = base.getPort(); + String port = ((p != -1) && (p != base.getDefaultPort())) ? ":" + p : ""; + if (fragment.startsWith("/")) { + return base.getProtocol() + "://" + base.getHost() + port + fragment; + } + return stripQueryString(base.toString()) + "/" + fragment; + } + + /** + * Register our TrustedSocketFactory for https connections + */ + @SuppressWarnings("deprecation") + public static void registerTrustedSocketFactory() { + Protocol.registerProtocol("https", + new Protocol("https", new TrustedSocketFactory(), 443)); + } + + /** + * Get a HTTP Client instance + * @param status the mobile BKU status + * @return the HttpClient + */ + public static HttpClient getHttpClient(ATrustStatus status) { + return BKUHelper.getHttpClient(true); + } + + /*** + * + * @param htmlString describes the html data in String representation + * @param attributeName is the attribute which should be selected + * @return returns the attribute name or null otherswise + */ + public static String getDynamicNameAttribute(String htmlString, String attributeName) { + + Document doc = Jsoup.parse(htmlString); + Elements inputs = doc.select("div input#" + attributeName); + + if (inputs.size() == 0 ) return null; + + String name = inputs.get(0).attr("name"); + return name; + } +} diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/MobileBKUs.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/MobileBKUs.java new file mode 100644 index 00000000..31339d9f --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/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.OLDmobile; + +/** + * 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/OLDmobile/SimpleXMLTrustManager.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/SimpleXMLTrustManager.java new file mode 100644 index 00000000..5f8bec31 --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/SimpleXMLTrustManager.java @@ -0,0 +1,220 @@ +/* + * 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.OLDmobile; + +// 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.commons.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"); + 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; + } + } + + /* + * 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(); + NodeList certificateList = certificates.getChildNodes(); + + try { + if (!certificates.getNodeName().equals("certificates")) { + throw new Exception("Used certificates xml is invalid! no certificates node"); + } + + //add trusted certificates to certStore// + for (int i = 0; i < certificateList.getLength(); i++) { + try { + + Node certificateNode = certificateList.item(i); + + if (certificateNode.getNodeName().equals("#text")) { + continue; // Ignore dummy text node .. + } + + if (!certificateNode.getNodeName().equals("certificate")) { + log.warn("Ignoring XML node: " + certificateNode.getNodeName()); + continue; + } + + String certResource = Constants.RES_CERT_PATH + certificateNode.getTextContent(); + + X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X509"). + generateCertificate(this.getClass().getResourceAsStream(certResource)); + + myKeyStore.setCertificateEntry(certificateNode.getTextContent(), cert); + + log.debug("Loaded certificate : " + certResource); + + } catch (Exception ex) { + log.error("Failed to load certificate [" + "]", ex); + } + } + + } + + catch (Exception e) { + e.toString(); + } + + 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-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); + 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); + 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/OLDmobile/TrustedSocketFactory.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/TrustedSocketFactory.java new file mode 100644 index 00000000..e6402a9d --- /dev/null +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/OLDmobile/TrustedSocketFactory.java @@ -0,0 +1,191 @@ +/* + * 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.OLDmobile; + +// 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.commons.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", + "SSL_RSA_WITH_RC4_128_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_RC4_128_MD5" + }; + + private static SSLSocketFactory getFactory() throws NoSuchAlgorithmException, + KeyManagementException, Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + 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); + 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-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); + 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-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"); + } + 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); + 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-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); + if (ex instanceof IOException) { + throw (IOException) ex; + } else if (ex instanceof UnknownHostException) { + throw (UnknownHostException) ex; + } else { + throw new IOException( + Messages.getString("TrustedSocketFactory.FailedToCreateSecureConnection"), ex); + } + } + } + +} -- cgit v1.2.3