diff options
Diffstat (limited to 'pdf-over-gui/src')
4 files changed, 145 insertions, 18 deletions
| diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/MobileBKUConnector.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/MobileBKUConnector.java index 34b53173..dae4d007 100644 --- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/MobileBKUConnector.java +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/MobileBKUConnector.java @@ -15,10 +15,15 @@   */
  package at.asit.pdfover.gui.bku;
 +import java.util.Base64;
 +
  // Imports
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
 +import com.google.gson.JsonNull;
 +import com.google.gson.JsonObject;
 +
  import at.asit.pdfover.gui.bku.mobile.ATrustHandler;
  import at.asit.pdfover.gui.bku.mobile.ATrustStatus;
  import at.asit.pdfover.gui.bku.mobile.MobileBKUHandler;
 @@ -29,6 +34,11 @@ import at.asit.pdfover.signator.SLRequest;  import at.asit.pdfover.signator.SLResponse;
  import at.asit.pdfover.signator.SignatureException;
  import at.asit.pdfover.signer.pdfas.PdfAs4SigningState;
 +import at.asit.webauthn.PublicKeyCredential;
 +import at.asit.webauthn.PublicKeyCredentialRequestOptions;
 +import at.asit.webauthn.WebAuthN;
 +import at.asit.webauthn.exceptions.WebAuthNOperationFailed;
 +import at.asit.webauthn.responsefields.AuthenticatorAssertionResponse;
  /**
   *
 @@ -125,6 +135,51 @@ public class MobileBKUConnector implements BkuSlConnector {  				if (status instanceof ATrustStatus) {
  					ATrustStatus aStatus = (ATrustStatus) status;
  					ATrustHandler aHandler = (ATrustHandler) handler;
 +					if (aStatus.fido2OptionAvailable && (aStatus.fido2FormOptions == null)) {
 +						try {
 +							handler.handleCredentialsResponse(aHandler.postFIDO2Request());
 +						} catch (Exception ex) {
 +							log.error("Error in PostCredentialsThread", ex);
 +							this.state.threadException = ex;
 +							throw new SignatureException(ex);
 +						}
 +					}
 +					if (aStatus.fido2FormOptions != null) {
 +						log.info("Fido2 credentials GET!");
 +						if (WebAuthN.isAvailable())
 +						{
 +							log.info("Authenticating with WebAuthn!");
 +							enterTAN = false;
 +							try {
 +								PublicKeyCredential<AuthenticatorAssertionResponse> credential = 
 +									PublicKeyCredentialRequestOptions.FromJSONString(aStatus.fido2FormOptions.get(aStatus.fido2OptionsKey)).get("https://service.a-trust.at");
 +								
 +								Base64.Encoder base64 = Base64.getEncoder();
 +								JsonObject aTrustCredential = new JsonObject();
 +								aTrustCredential.addProperty("id", credential.id);
 +								aTrustCredential.addProperty("rawId", base64.encodeToString(credential.rawId));
 +								aTrustCredential.addProperty("type", credential.type);
 +								aTrustCredential.add("extensions", new JsonObject()); // TODO fix getClientExtensionResults() in library
 +
 +								JsonObject aTrustCredentialResponse = new JsonObject();
 +								aTrustCredential.add("response", aTrustCredentialResponse);
 +								aTrustCredentialResponse.addProperty("authenticatorData", base64.encodeToString(credential.response.authenticatorData));
 +								aTrustCredentialResponse.addProperty("clientDataJson", base64.encodeToString(credential.response.clientDataJSON));
 +								aTrustCredentialResponse.addProperty("signature", base64.encodeToString(credential.response.signature));
 +								if (credential.response.userHandle != null)
 +									aTrustCredentialResponse.addProperty("userHandle", base64.encodeToString(credential.response.userHandle));
 +								else
 +									aTrustCredentialResponse.add("userHandle", JsonNull.INSTANCE);
 +
 +								aStatus.fido2FormOptions.put(aStatus.fido2ResultKey, aTrustCredential.toString());
 +								handler.handleTANResponse(aHandler.postFIDO2Result()); // TODO dedicated response
 +							} catch (WebAuthNOperationFailed e) {
 +								log.error("WebAuthN failed", e);
 +							} catch (Exception e) {
 +								log.error("generic failure", e);
 +							}
 +						}
 +					}
  					if (aStatus.qrCodeURL != null) {
  						this.state.showQR();
  						if ("cancel".equals(this.state.status.errorMessage))
 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 index 18f93b22..5e4975e3 100644 --- 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 @@ -21,16 +21,22 @@ import java.io.BufferedInputStream;  import java.io.IOException;
  import java.io.InputStream;
  import java.net.URI;
 +import java.util.HashMap;
 +import java.util.Map;
  import org.apache.commons.httpclient.HttpClient;
  import org.apache.commons.httpclient.HttpStatus;
  import org.apache.commons.httpclient.methods.GetMethod;
  import org.apache.commons.httpclient.methods.PostMethod;
  import org.apache.commons.io.IOUtils;
 +import org.apache.commons.lang.StringEscapeUtils;
  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;
 @@ -149,7 +155,7 @@ public class ATrustHandler extends MobileBKUHandler {  	 * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleCredentialsResponse(java.lang.String)
  	 */
  	@Override
 -	public void handleCredentialsResponse(String responseData) throws Exception {
 +	public void handleCredentialsResponse(final String responseData) throws Exception {
  		ATrustStatus status = getStatus();
  		String viewState = status.viewState;
  		String eventValidation = status.eventValidation;
 @@ -160,6 +166,8 @@ public class ATrustHandler extends MobileBKUHandler {  		status.errorMessage = null;
 +		final Document responseDocument = Jsoup.parse(responseData);
 +
  		if (responseData.contains("ExpiresInfo.aspx?sid=")) {
  			// Certificate expiration interstitial - skip
  			if (!expiryNoticeDisplayed) {
 @@ -196,8 +204,8 @@ public class ATrustHandler extends MobileBKUHandler {  			post.addParameter("__EVENTVALIDATION", t_eventValidation);
  			post.addParameter("Button_Next", "Weiter");
 -			responseData = executePost(client, post);
 -			log.trace("Response from mobile BKU: " + responseData);
 +			handleCredentialsResponse(executePost(client, post));
 +			return;
  		} else if (responseData.contains("tanAppInfo.aspx?sid=")) {
  			// App info interstitial - skip
  			log.info("Skipping tan app interstitial");
 @@ -216,8 +224,8 @@ public class ATrustHandler extends MobileBKUHandler {  			post.addParameter("__EVENTVALIDATION", t_eventValidation);
  			post.addParameter("NextBtn", "Weiter");
 -			responseData = executePost(client, post);
 -			log.trace("Response from mobile BKU: " + responseData);
 +			handleCredentialsResponse(executePost(client, post));
 +			return;
  		}
  		if (responseData.contains("signature.aspx?sid=")) {
 @@ -227,7 +235,12 @@ public class ATrustHandler extends MobileBKUHandler {  			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'><b>Vergleichswert:</b>", "</div>");
 +			try {
 +				refVal = MobileBKUHelper.extractSubstring(responseData, "id='vergleichswert'><b>Vergleichswert:</b>", "</div>");
 +			} catch (Exception e) {
 +				refVal = null;
 +				log.debug("No reference value");
 +			}
  			signatureDataURL = status.baseURL + "/ShowSigobj.aspx" +
  					MobileBKUHelper.extractSubstring(responseData, "ShowSigobj.aspx", "'");
  			try {
 @@ -253,17 +266,27 @@ public class ATrustHandler extends MobileBKUHandler {  			}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");
 +			
 +			status.fido2OptionAvailable = (responseDocument.selectFirst("#FidoButton") != null);
 +			{
 +				Element fidoBlock = responseDocument.selectFirst("#fidoBlock");
 +
 +				if (fidoBlock != null) {
 +					Map<String,String> options = new HashMap<>();
 +					for (Element field : fidoBlock.select("input"))
 +					{
 +						if (!field.hasAttr("name"))
 +							continue;
 +						options.put(field.attr("name"), field.attr("value"));
 +						if ("credentialOptions".equals(field.attr("id")))
 +							status.fido2OptionsKey = field.attr("name");
 +						if ("credentialResult".equals(field.attr("id")))
 +							status.fido2ResultKey = field.attr("name");
 +					}
 +					log.info("Fido credential options: {}", options);
 +					status.fido2FormOptions = options;
 +					status.qrCodeURL = null;
 +				}
  			}
  		} else if (responseData.contains("sl:InfoboxReadResponse")) {
 @@ -341,6 +364,7 @@ public class ATrustHandler extends MobileBKUHandler {  		return executePost(client, post);
  	}
 +
  	/* (non-Javadoc)
  	 * @see at.asit.pdfover.gui.workflow.states.mobilebku.MobileBKUHandler#handleTANResponse(java.lang.String)
  	 */
 @@ -402,6 +426,40 @@ public class ATrustHandler extends MobileBKUHandler {  	}
  	/**
 +	 * Cancel QR process, request FIDO2 authentication
 +	 * @return the response
 +	 * @throws IOException Error during posting
 +	 */
 +
 +	public String postFIDO2Request() throws IOException {
 +		ATrustStatus status = getStatus();
 +
 +		MobileBKUHelper.registerTrustedSocketFactory();
 +		HttpClient client = MobileBKUHelper.getHttpClient(status);
 +		GetMethod get = new GetMethod(status.baseURL + "/usefido.aspx?sid=" + status.sessionID);
 +		get.getParams().setContentCharset("utf-8");
 +
 +		return executeGet(client, get);
 +	}
 +
 +	public String postFIDO2Result() throws IOException {
 +		ATrustStatus status = getStatus();
 +
 +		MobileBKUHelper.registerTrustedSocketFactory();
 +		HttpClient client = MobileBKUHelper.getHttpClient(status);
 +
 +		PostMethod post = new PostMethod(status.baseURL + "/signature.aspx?sid=" + status.sessionID);
 +		post.getParams().setContentCharset("utf-8");
 +		post.addParameter("__VIEWSTATE", status.viewState);
 +		post.addParameter("__VIEWSTATEGENERATOR", status.viewStateGenerator);
 +		post.addParameter("__EVENTVALIDATION", status.eventValidation);
 +		for (Map.Entry<String, String> entry : status.fido2FormOptions.entrySet())
 +			post.addParameter(entry.getKey(), entry.getValue());
 +
 +		return executePost(client, post);
 +	}
 +
 +	/**
  	 * Get the QR code image
  	 * @return the QR code image as a String
  	 */
 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 index b61b3a8b..6258b4ce 100644 --- 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 @@ -15,6 +15,8 @@   */
  package at.asit.pdfover.gui.bku.mobile;
 +import java.util.Map;
 +
  // Imports
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
 @@ -47,6 +49,11 @@ public class ATrustStatus extends MobileBKUStatus {  	public String dynAttrSignButton;
  	public boolean isSMSTan = false;
 +	public boolean fido2OptionAvailable = false;
 +	public String fido2OptionsKey;
 +	public String fido2ResultKey;
 +	public Map<String,String> fido2FormOptions;
 +
  	/**
  	 * Constructor
  	 * @param provider the ConfigProvider
 diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/MobileBKUQRComposite.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/MobileBKUQRComposite.java index 121d8c71..1a1a10ac 100644 --- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/MobileBKUQRComposite.java +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/MobileBKUQRComposite.java @@ -21,6 +21,7 @@ import java.io.InputStream;  import java.net.URI;
  import org.eclipse.swt.SWT;
 +import org.eclipse.swt.SWTException;
  import org.eclipse.swt.events.PaintEvent;
  import org.eclipse.swt.events.PaintListener;
  import org.eclipse.swt.events.SelectionAdapter;
 @@ -226,7 +227,13 @@ public class MobileBKUQRComposite extends StateComposite {  			setErrorMessage(Messages.getString("error.FailedToLoadQRCode"));
  			return;
  		}
 -		this.currentQRImage = new ImageData(qrcode);
 +		try {
 +			this.currentQRImage = new ImageData(qrcode);
 +		} catch (SWTException e) {
 +			log.warn("Failed to load QR code", e);
 +			setErrorMessage(Messages.getString("error.FailedToLoadQRCode"));
 +			return;
 +		}
  		updateQRImage();
  	}
 | 
