Search in sources :

Example 1 with InvalidRedirectUrlException

use of org.openecard.binding.tctoken.ex.InvalidRedirectUrlException in project open-ecard by ecsec.

the class TCTokenHandler method determineRefreshURL.

/**
 * Follow the URL in the RefreshAddress and update it in the response.
 * The redirect is followed as long as the response is a redirect (302, 303 or 307) AND is a
 * https-URL AND the hash of the retrieved server certificate is contained in the CertificateDescrioption, else
 * return 400. If the URL and the subjectURL in the CertificateDescription conform to the SOP we reached our final
 * destination.
 *
 * @param request TCToken request used to determine which security checks to perform.
 * @param response The TCToken response in which the original refresh address is defined and where it will be
 *	 updated.
 * @return Modified response with the final address the browser should be redirected to.
 * @throws InvalidRedirectUrlException Thrown in case no redirect URL could be determined.
 */
private static TCTokenResponse determineRefreshURL(TCTokenRequest request, TCTokenResponse response) throws InvalidRedirectUrlException, SecurityViolationException {
    try {
        String endpointStr = response.getRefreshAddress();
        URL endpoint = new URL(endpointStr);
        DynamicContext dynCtx = DynamicContext.getInstance(TR03112Keys.INSTANCE_KEY);
        // omit checks completely if this is an object tag activation
        Object objectActivation = dynCtx.get(TR03112Keys.OBJECT_ACTIVATION);
        if (objectActivation instanceof Boolean && ((Boolean) objectActivation) == true) {
            return response;
        }
        // disable certificate checks according to BSI TR03112-7 in some situations
        boolean redirectChecks = isPerformTR03112Checks(request);
        RedirectCertificateValidator verifier = new RedirectCertificateValidator(redirectChecks);
        ResourceContext ctx = ResourceContext.getStream(endpoint, verifier);
        ctx.closeStream();
        // using this verifier no result must be present, meaning no status code different than a redirect occurred
        // if (result.p1 != null) {
        // // TODO: this error is expected according the spec, handle it in a different way
        // String msg = "Return-To-Websession yielded a non-redirect response.";
        // throw new IOException(msg);
        // }
        // determine redirect
        List<Pair<URL, TlsServerCertificate>> resultPoints = ctx.getCerts();
        Pair<URL, TlsServerCertificate> last = resultPoints.get(resultPoints.size() - 1);
        endpoint = last.p1;
        dynCtx.put(TR03112Keys.IS_REFRESH_URL_VALID, true);
        LOG.debug("Setting redirect address to '{}'.", endpoint);
        response.setRefreshAddress(endpoint.toString());
        return response;
    } catch (MalformedURLException ex) {
        throw new IllegalStateException(LANG_TR.translationForKey(REFRESH_URL_ERROR), ex);
    } catch (ResourceException | InvalidAddressException | ValidationError | IOException ex) {
        String code = ECardConstants.Minor.App.COMMUNICATION_ERROR;
        String communicationErrorAddress = response.getTCToken().getComErrorAddressWithParams(code);
        if (communicationErrorAddress != null && !communicationErrorAddress.isEmpty()) {
            throw new SecurityViolationException(communicationErrorAddress, REFRESH_DETERMINATION_FAILED, ex);
        }
        throw new InvalidRedirectUrlException(REFRESH_DETERMINATION_FAILED, ex);
    }
}
Also used : InvalidRedirectUrlException(org.openecard.binding.tctoken.ex.InvalidRedirectUrlException) MalformedURLException(java.net.MalformedURLException) SecurityViolationException(org.openecard.binding.tctoken.ex.SecurityViolationException) IOException(java.io.IOException) URL(java.net.URL) TlsServerCertificate(org.openecard.bouncycastle.tls.TlsServerCertificate) InvalidAddressException(org.openecard.binding.tctoken.ex.InvalidAddressException) DynamicContext(org.openecard.common.DynamicContext) Pair(org.openecard.common.util.Pair)

Example 2 with InvalidRedirectUrlException

use of org.openecard.binding.tctoken.ex.InvalidRedirectUrlException in project open-ecard by ecsec.

the class TCTokenHandler method handleActivate.

/**
 * Activates the client according to the received TCToken.
 *
 * @param request The activation request containing the TCToken.
 * @return The response containing the result of the activation process.
 * @throws InvalidRedirectUrlException Thrown in case no redirect URL could be determined.
 * @throws SecurityViolationException
 * @throws NonGuiException
 */
public TCTokenResponse handleActivate(TCTokenRequest request) throws InvalidRedirectUrlException, SecurityViolationException, NonGuiException {
    TCToken token = request.getTCToken();
    if (LOG.isDebugEnabled()) {
        try {
            WSMarshaller m = WSMarshallerFactory.createInstance();
            LOG.debug("TCToken:\n{}", m.doc2str(m.marshal(token)));
        } catch (TransformerException | WSMarshallerException ex) {
        // it's no use
        }
    }
    final DynamicContext dynCtx = DynamicContext.getInstance(TR03112Keys.INSTANCE_KEY);
    boolean performChecks = isPerformTR03112Checks(request);
    if (!performChecks) {
        LOG.warn("Checks according to BSI TR03112 3.4.2, 3.4.4 (TCToken specific) and 3.4.5 are disabled.");
    }
    boolean isObjectActivation = request.getTCTokenURL() == null;
    if (isObjectActivation) {
        LOG.warn("Checks according to BSI TR03112 3.4.4 (TCToken specific) are disabled.");
    }
    dynCtx.put(TR03112Keys.TCTOKEN_CHECKS, performChecks);
    dynCtx.put(TR03112Keys.OBJECT_ACTIVATION, isObjectActivation);
    dynCtx.put(TR03112Keys.TCTOKEN_SERVER_CERTIFICATES, request.getCertificates());
    ConnectionHandleType connectionHandle = null;
    TCTokenResponse response = new TCTokenResponse();
    response.setTCToken(token);
    byte[] requestedContextHandle = request.getContextHandle();
    String ifdName = request.getIFDName();
    BigInteger requestedSlotIndex = request.getSlotIndex();
    // we know exactly which card we want
    ConnectionHandleType requestedHandle = new ConnectionHandleType();
    requestedHandle.setContextHandle(requestedContextHandle);
    requestedHandle.setIFDName(ifdName);
    requestedHandle.setSlotIndex(requestedSlotIndex);
    Set<CardStateEntry> matchingHandles = cardStates.getMatchingEntries(requestedHandle);
    if (!matchingHandles.isEmpty()) {
        connectionHandle = matchingHandles.toArray(new CardStateEntry[] {})[0].handleCopy();
    }
    if (connectionHandle == null) {
        String msg = LANG_TOKEN.translationForKey("cancel");
        LOG.error(msg);
        response.setResult(WSHelper.makeResultError(ResultMinor.CANCELLATION_BY_USER, msg));
        // fill in values, so it is usuable by the transport module
        response = determineRefreshURL(request, response);
        response.finishResponse(true);
        return response;
    }
    try {
        // process binding and follow redirect addresses afterwards
        response = processBinding(request, connectionHandle);
        // fill in values, so it is usuable by the transport module
        response = determineRefreshURL(request, response);
        response.finishResponse(isObjectActivation);
        return response;
    } catch (DispatcherException w) {
        LOG.error(w.getMessage(), w);
        response.setResultCode(BindingResultCode.INTERNAL_ERROR);
        response.setResult(WSHelper.makeResultError(ResultMinor.CLIENT_ERROR, w.getMessage()));
        showErrorMessage(w.getMessage());
        throw new NonGuiException(response, w.getMessage(), w);
    } catch (PAOSException w) {
        LOG.error(w.getMessage(), w);
        // find actual error to display to the user
        Throwable innerException = w.getCause();
        if (innerException == null) {
            innerException = w;
        } else if (innerException instanceof ExecutionException) {
            innerException = innerException.getCause();
        }
        String errorMsg = innerException.getLocalizedMessage();
        // fix NPE when null is returned instead of a message
        errorMsg = errorMsg == null ? "" : errorMsg;
        switch(errorMsg) {
            case "The target server failed to respond":
                errorMsg = LANG_TR.translationForKey(NO_RESPONSE_FROM_SERVER);
                break;
            case ECardConstants.Minor.App.INT_ERROR + " ==> Unknown eCard exception occurred.":
                errorMsg = LANG_TR.translationForKey(UNKNOWN_ECARD_ERROR);
                break;
            case "Internal TLS error, this could be an attack":
                errorMsg = LANG_TR.translationForKey(INTERNAL_TLS_ERROR);
                break;
        }
        if (innerException instanceof WSException) {
            WSException ex = (WSException) innerException;
            errorMsg = createResponseFromWsEx(ex, response);
        } else if (innerException instanceof PAOSConnectionException) {
            response.setResult(WSHelper.makeResultError(ResultMinor.TRUSTED_CHANNEL_ESTABLISCHMENT_FAILED, w.getLocalizedMessage()));
        } else {
            errorMsg = createMessageFromUnknownError(w);
            response.setResult(WSHelper.makeResultError(ResultMinor.CLIENT_ERROR, w.getMessage()));
        }
        showErrorMessage(errorMsg);
        try {
            // fill in values, so it is usuable by the transport module
            response = determineRefreshURL(request, response);
            response.finishResponse(true);
        } catch (InvalidRedirectUrlException ex) {
            LOG.error(ex.getMessage(), ex);
            response.setResultCode(BindingResultCode.INTERNAL_ERROR);
            response.setResult(WSHelper.makeResultError(ResultMinor.CLIENT_ERROR, ex.getLocalizedMessage()));
            throw new NonGuiException(response, ex.getMessage(), ex);
        } catch (SecurityViolationException ex) {
            String msg2 = "The RefreshAddress contained in the TCToken is invalid. Redirecting to the " + "CommunicationErrorAddress.";
            LOG.error(msg2, ex);
            response.setResultCode(BindingResultCode.REDIRECT);
            response.setResult(WSHelper.makeResultError(ResultMinor.COMMUNICATION_ERROR, msg2));
            response.addAuxResultData(AuxDataKeys.REDIRECT_LOCATION, ex.getBindingResult().getAuxResultData().get(AuxDataKeys.REDIRECT_LOCATION));
        }
        return response;
    }
}
Also used : ConnectionHandleType(iso.std.iso_iec._24727.tech.schema.ConnectionHandleType) InvalidRedirectUrlException(org.openecard.binding.tctoken.ex.InvalidRedirectUrlException) CardStateEntry(org.openecard.common.sal.state.CardStateEntry) WSMarshallerException(org.openecard.ws.marshal.WSMarshallerException) SecurityViolationException(org.openecard.binding.tctoken.ex.SecurityViolationException) WSMarshaller(org.openecard.ws.marshal.WSMarshaller) DispatcherException(org.openecard.common.interfaces.DispatcherException) PAOSException(org.openecard.transport.paos.PAOSException) PAOSConnectionException(org.openecard.transport.paos.PAOSConnectionException) BigInteger(java.math.BigInteger) WSException(org.openecard.common.WSHelper.WSException) NonGuiException(org.openecard.binding.tctoken.ex.NonGuiException) ExecutionException(java.util.concurrent.ExecutionException) TransformerException(javax.xml.transform.TransformerException) DynamicContext(org.openecard.common.DynamicContext)

Example 3 with InvalidRedirectUrlException

use of org.openecard.binding.tctoken.ex.InvalidRedirectUrlException in project open-ecard by ecsec.

the class TCToken method getComErrorAddressWithParams.

/**
 * Gets the CommunicationErrorAddress for use in error conditions.
 * If the CommunicationErrorAddress is available this one is used.
 *
 * @param minor The ResultMinor string.
 * @return The error URL.
 * @throws InvalidRedirectUrlException In case the address is not present or a valid URL.
 */
public String getComErrorAddressWithParams(@Nonnull String minor) throws InvalidRedirectUrlException {
    try {
        String errorUrl = getCommunicationErrorAddress();
        URI url = checkUrl(errorUrl);
        String result = UrlBuilder.fromUrl(url).queryParam("ResultMajor", "error").queryParamUrl("ResultMinor", TCTokenHacks.fixResultMinor(minor)).build().toString();
        return result;
    } catch (URISyntaxException ex) {
        // should not happen, but here it is anyways
        LOG.error("Construction of redirect URL failed.", ex);
        throw new InvalidRedirectUrlException(NO_URL);
    }
}
Also used : InvalidRedirectUrlException(org.openecard.binding.tctoken.ex.InvalidRedirectUrlException) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI)

Aggregations

InvalidRedirectUrlException (org.openecard.binding.tctoken.ex.InvalidRedirectUrlException)3 SecurityViolationException (org.openecard.binding.tctoken.ex.SecurityViolationException)2 DynamicContext (org.openecard.common.DynamicContext)2 ConnectionHandleType (iso.std.iso_iec._24727.tech.schema.ConnectionHandleType)1 IOException (java.io.IOException)1 BigInteger (java.math.BigInteger)1 MalformedURLException (java.net.MalformedURLException)1 URI (java.net.URI)1 URISyntaxException (java.net.URISyntaxException)1 URL (java.net.URL)1 ExecutionException (java.util.concurrent.ExecutionException)1 TransformerException (javax.xml.transform.TransformerException)1 InvalidAddressException (org.openecard.binding.tctoken.ex.InvalidAddressException)1 NonGuiException (org.openecard.binding.tctoken.ex.NonGuiException)1 TlsServerCertificate (org.openecard.bouncycastle.tls.TlsServerCertificate)1 WSException (org.openecard.common.WSHelper.WSException)1 DispatcherException (org.openecard.common.interfaces.DispatcherException)1 CardStateEntry (org.openecard.common.sal.state.CardStateEntry)1 Pair (org.openecard.common.util.Pair)1 PAOSConnectionException (org.openecard.transport.paos.PAOSConnectionException)1