Search in sources :

Example 1 with Pair

use of org.openecard.common.util.Pair in project open-ecard by ecsec.

the class PACEStep method checkTCTokenServerCertificates.

private boolean checkTCTokenServerCertificates(CertificateDescription certDescription, DynamicContext dynCtx) {
    List<Pair<URL, TlsServerCertificate>> certificates;
    certificates = (List<Pair<URL, TlsServerCertificate>>) dynCtx.get(TR03112Keys.TCTOKEN_SERVER_CERTIFICATES);
    if (certificates != null) {
        for (Pair<URL, TlsServerCertificate> cert : certificates) {
            if (cert instanceof Pair) {
                URL u = cert.p1;
                String host = u.getProtocol() + "://" + u.getHost() + (u.getPort() == -1 ? "" : (":" + u.getPort()));
                TlsServerCertificate bcCert = cert.p2;
                if (!TR03112Utils.isInCommCertificates(bcCert, certDescription.getCommCertificates(), host)) {
                    return false;
                }
            }
        }
        return true;
    } else {
        LOG.error("No TC Token server certificates set in Dynamic Context.");
        return false;
    }
}
Also used : TlsServerCertificate(org.openecard.bouncycastle.tls.TlsServerCertificate) URL(java.net.URL) Pair(org.openecard.common.util.Pair)

Example 2 with Pair

use of org.openecard.common.util.Pair in project open-ecard by ecsec.

the class ResourceContext method getStreamInt.

private static ResourceContext getStreamInt(URL url, CertificateValidator v, List<Pair<URL, TlsServerCertificate>> serverCerts, int maxRedirects) throws IOException, ResourceException, ValidationError, InvalidAddressException {
    try {
        DynamicContext dynCtx = DynamicContext.getInstance(TR03112Keys.INSTANCE_KEY);
        CookieManager cManager = (CookieManager) dynCtx.get(TR03112Keys.COOKIE_MANAGER);
        LOG.info("Trying to load resource from: {}", url);
        if (maxRedirects == 0) {
            throw new ResourceException(MAX_REDIRECTS);
        }
        maxRedirects--;
        String protocol = url.getProtocol();
        String hostname = url.getHost();
        int port = url.getPort();
        if (port == -1) {
            port = url.getDefaultPort();
        }
        String resource = url.getFile();
        resource = resource.isEmpty() ? "/" : resource;
        if (!"https".equals(protocol)) {
            throw new InvalidAddressException(INVALID_ADDRESS);
        }
        // open a TLS connection, retrieve the server certificate and save it
        TlsClientProtocol h;
        DynamicAuthentication tlsAuth = new DynamicAuthentication(hostname);
        // add PKIX validator if not doin nPA auth
        if (isPKIXVerify()) {
            tlsAuth.addCertificateVerifier(new JavaSecVerifier());
        }
        // FIXME: validate certificate chain as soon as a usable solution exists for the trust problem
        // tlsAuth.setCertificateVerifier(new JavaSecVerifier());
        TlsCrypto crypto = new BcTlsCrypto(ReusableSecureRandom.getInstance());
        ClientCertTlsClient tlsClient = new ClientCertDefaultTlsClient(crypto, hostname, true);
        tlsClient.setAuthentication(tlsAuth);
        // connect tls client
        tlsClient.setClientVersion(ProtocolVersion.TLSv12);
        Socket socket = ProxySettings.getDefault().getSocket(protocol, hostname, port);
        h = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream());
        LOG.debug("Performing TLS handshake.");
        h.connect(tlsClient);
        LOG.debug("TLS handshake performed.");
        serverCerts.add(new Pair<>(url, tlsAuth.getServerCertificate()));
        // check result
        CertificateValidator.VerifierResult verifyResult = v.validate(url, tlsAuth.getServerCertificate());
        if (verifyResult == CertificateValidator.VerifierResult.FINISH) {
            List<Pair<URL, TlsServerCertificate>> pairs = Collections.unmodifiableList(serverCerts);
            return new ResourceContext(tlsClient, h, pairs);
        }
        StreamHttpClientConnection conn = new StreamHttpClientConnection(h.getInputStream(), h.getOutputStream());
        HttpContext ctx = new BasicHttpContext();
        HttpRequestExecutor httpexecutor = new HttpRequestExecutor();
        BasicHttpEntityEnclosingRequest req = new BasicHttpEntityEnclosingRequest("GET", resource);
        HttpRequestHelper.setDefaultHeader(req, url);
        req.setHeader("Accept", "text/xml, */*;q=0.8");
        req.setHeader("Accept-Charset", "utf-8, *;q=0.8");
        setCookieHeader(req, cManager, url);
        HttpUtils.dumpHttpRequest(LOG, req);
        LOG.debug("Sending HTTP request.");
        HttpResponse response = httpexecutor.execute(req, conn, ctx);
        storeCookies(response, cManager, url);
        LOG.debug("HTTP response received.");
        StatusLine status = response.getStatusLine();
        int statusCode = status.getStatusCode();
        String reason = status.getReasonPhrase();
        HttpUtils.dumpHttpResponse(LOG, response, null);
        HttpEntity entity = null;
        boolean finished = false;
        if (TR03112Utils.isRedirectStatusCode(statusCode)) {
            Header[] headers = response.getHeaders("Location");
            if (headers.length > 0) {
                String uri = headers[0].getValue();
                url = new URL(uri);
            } else {
                // FIXME: refactor exception handling
                throw new ResourceException(MISSING_LOCATION_HEADER);
            }
        } else if (statusCode >= 400) {
            // according to the HTTP RFC, codes greater than 400 signal errors
            LOG.debug("Received a result code {} '{}' from server.", statusCode, reason);
            throw new InvalidResultStatus(LANG.translationForKey(INVALID_RESULT_STATUS, statusCode, reason));
        } else {
            if (verifyResult == CertificateValidator.VerifierResult.CONTINUE) {
                throw new InvalidAddressException(INVALID_REFRESH_ADDRESS_NOSOP);
            } else {
                conn.receiveResponseEntity(response);
                entity = response.getEntity();
                finished = true;
            }
        }
        // follow next redirect or finish?
        if (finished) {
            assert (entity != null);
            ResourceContext result = new ResourceContext(tlsClient, h, serverCerts);
            LimitedInputStream is = new LimitedInputStream(entity.getContent());
            result.setStream(is);
            return result;
        } else {
            h.close();
            return getStreamInt(url, v, serverCerts, maxRedirects);
        }
    } catch (URISyntaxException ex) {
        throw new IOException(LANG.translationForKey(FAILED_PROXY), ex);
    } catch (HttpException ex) {
        // don't translate this, it is handled in the ActivationAction
        throw new IOException("Invalid HTTP message received.", ex);
    }
}
Also used : HttpRequestExecutor(org.openecard.apache.http.protocol.HttpRequestExecutor) HttpEntity(org.openecard.apache.http.HttpEntity) BasicHttpContext(org.openecard.apache.http.protocol.BasicHttpContext) LimitedInputStream(org.openecard.common.io.LimitedInputStream) TlsClientProtocol(org.openecard.bouncycastle.tls.TlsClientProtocol) URISyntaxException(java.net.URISyntaxException) ClientCertTlsClient(org.openecard.crypto.tls.ClientCertTlsClient) StreamHttpClientConnection(org.openecard.transport.httpcore.StreamHttpClientConnection) URL(java.net.URL) TlsCrypto(org.openecard.bouncycastle.tls.crypto.TlsCrypto) BcTlsCrypto(org.openecard.bouncycastle.tls.crypto.impl.bc.BcTlsCrypto) HttpException(org.openecard.apache.http.HttpException) CookieManager(org.openecard.transport.httpcore.cookies.CookieManager) JavaSecVerifier(org.openecard.crypto.tls.verify.JavaSecVerifier) InvalidResultStatus(org.openecard.transport.httpcore.InvalidResultStatus) Pair(org.openecard.common.util.Pair) BasicHttpEntityEnclosingRequest(org.openecard.apache.http.message.BasicHttpEntityEnclosingRequest) BasicHttpContext(org.openecard.apache.http.protocol.BasicHttpContext) HttpContext(org.openecard.apache.http.protocol.HttpContext) ClientCertDefaultTlsClient(org.openecard.crypto.tls.ClientCertDefaultTlsClient) HttpResponse(org.openecard.apache.http.HttpResponse) BcTlsCrypto(org.openecard.bouncycastle.tls.crypto.impl.bc.BcTlsCrypto) IOException(java.io.IOException) StatusLine(org.openecard.apache.http.StatusLine) Header(org.openecard.apache.http.Header) DynamicAuthentication(org.openecard.crypto.tls.auth.DynamicAuthentication) InvalidAddressException(org.openecard.binding.tctoken.ex.InvalidAddressException) Socket(java.net.Socket) DynamicContext(org.openecard.common.DynamicContext)

Example 3 with Pair

use of org.openecard.common.util.Pair in project open-ecard by ecsec.

the class TCTokenContext method generateTCToken.

private static TCTokenContext generateTCToken(String data, ResourceContext base) throws InvalidTCTokenException, AuthServerException, InvalidRedirectUrlException, InvalidTCTokenElement, InvalidTCTokenUrlException, SecurityViolationException, UserCancellationException {
    // correct common TCToken shortcomings
    data = TCTokenHacks.fixPathSecurityParameters(data);
    LOG.debug("Cleaned up TCToken:\n{}", data);
    // Parse the TCToken
    TCTokenParser parser = new TCTokenParser();
    List<TCToken> tokens = parser.parse(data);
    if (tokens.isEmpty()) {
        throw new InvalidTCTokenException(NO_TCTOKEN_IN_DATA);
    }
    // Verify the TCToken
    TCToken token = tokens.get(0);
    TCTokenVerifier ver = new TCTokenVerifier(token, base);
    if (ver.isErrorToken()) {
        String minor = ResultMinor.CLIENT_ERROR;
        throw new AuthServerException(token.getComErrorAddressWithParams(minor), ESERVICE_ERROR);
    }
    DynamicContext dynCtx = DynamicContext.getInstance(TR03112Keys.INSTANCE_KEY);
    List<Pair<URL, TlsServerCertificate>> resultPoints = base.getCerts();
    // probably just for tests
    if (!resultPoints.isEmpty()) {
        Pair<URL, TlsServerCertificate> last = resultPoints.get(0);
        dynCtx.put(TR03112Keys.TCTOKEN_URL, last.p1);
    }
    ver.verifyUrlToken();
    return new TCTokenContext(token, base);
}
Also used : URL(java.net.URL) TlsServerCertificate(org.openecard.bouncycastle.tls.TlsServerCertificate) InvalidTCTokenException(org.openecard.binding.tctoken.ex.InvalidTCTokenException) AuthServerException(org.openecard.binding.tctoken.ex.AuthServerException) DynamicContext(org.openecard.common.DynamicContext) Pair(org.openecard.common.util.Pair)

Example 4 with Pair

use of org.openecard.common.util.Pair 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 5 with Pair

use of org.openecard.common.util.Pair in project open-ecard by ecsec.

the class TCTokenVerifier method assertSameChannel.

private void assertSameChannel(String name, String address) throws InvalidRedirectUrlException, InvalidTCTokenUrlException, SecurityViolationException {
    // check that everything can be handled over the same channel
    // TR-03124-1 does not mention that redirects on the TCToken address are possible and it also states that there
    // are only two channels. So I guess we should force this here as well.
    URL paosUrl = assertURL(name, address);
    List<Pair<URL, TlsServerCertificate>> urls = ctx.getCerts();
    for (Pair<URL, TlsServerCertificate> next : urls) {
        if (!TR03112Utils.checkSameOriginPolicy(paosUrl, next.p1)) {
            String minor = ResultMinor.COMMUNICATION_ERROR;
            String errorUrl = token.getComErrorAddressWithParams(minor);
            throw new SecurityViolationException(errorUrl, FAILED_SOP);
        }
    }
}
Also used : TlsServerCertificate(org.openecard.bouncycastle.tls.TlsServerCertificate) SecurityViolationException(org.openecard.binding.tctoken.ex.SecurityViolationException) URL(java.net.URL) Pair(org.openecard.common.util.Pair)

Aggregations

URL (java.net.URL)6 Pair (org.openecard.common.util.Pair)6 TlsServerCertificate (org.openecard.bouncycastle.tls.TlsServerCertificate)5 IOException (java.io.IOException)3 InvalidAddressException (org.openecard.binding.tctoken.ex.InvalidAddressException)3 DynamicContext (org.openecard.common.DynamicContext)3 URISyntaxException (java.net.URISyntaxException)2 SecurityViolationException (org.openecard.binding.tctoken.ex.SecurityViolationException)2 MalformedURLException (java.net.MalformedURLException)1 Socket (java.net.Socket)1 URI (java.net.URI)1 Header (org.openecard.apache.http.Header)1 HttpEntity (org.openecard.apache.http.HttpEntity)1 HttpException (org.openecard.apache.http.HttpException)1 HttpResponse (org.openecard.apache.http.HttpResponse)1 StatusLine (org.openecard.apache.http.StatusLine)1 BasicHttpEntityEnclosingRequest (org.openecard.apache.http.message.BasicHttpEntityEnclosingRequest)1 BasicHttpContext (org.openecard.apache.http.protocol.BasicHttpContext)1 HttpContext (org.openecard.apache.http.protocol.HttpContext)1 HttpRequestExecutor (org.openecard.apache.http.protocol.HttpRequestExecutor)1