use of org.openecard.binding.tctoken.ex.InvalidAddressException 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);
}
}
use of org.openecard.binding.tctoken.ex.InvalidAddressException 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);
}
}
use of org.openecard.binding.tctoken.ex.InvalidAddressException in project open-ecard by ecsec.
the class TCTokenVerifier method determineRefreshAddress.
/**
* Determines the refresh URL.
*
* @param ex The exception which caused the abort of the TCToken verification.
* @throws InvalidRedirectUrlException If the CommunicationErrorAddress cant be determined.
* @throws InvalidTCTokenElement If a determination of a refresh or CommunicationError address was successful.
* @throws UserCancellationException Thrown in case {@code ex} is an instance of {@link UserCancellationException}.
*/
private void determineRefreshAddress(ActivationError ex) throws InvalidRedirectUrlException, InvalidTCTokenElement, UserCancellationException {
if (token.getRefreshAddress() != null) {
try {
CertificateValidator validator = new RedirectCertificateValidator(true);
ResourceContext newResCtx = ResourceContext.getStream(new URL(token.getRefreshAddress()), validator);
newResCtx.closeStream();
List<Pair<URL, TlsServerCertificate>> resultPoints = newResCtx.getCerts();
Pair<URL, TlsServerCertificate> last = resultPoints.get(resultPoints.size() - 1);
URL resAddr = last.p1;
String refreshUrl = resAddr.toString();
if (ex instanceof UserCancellationException) {
UserCancellationException uex = (UserCancellationException) ex;
URI refreshUrlAsUrl = createUrlWithErrorParams(refreshUrl, ResultMinor.CANCELLATION_BY_USER, ex.getMessage());
throw new UserCancellationException(refreshUrlAsUrl.toString(), ex);
}
URI refreshUrlAsUrl = createUrlWithErrorParams(refreshUrl, ResultMinor.TRUSTED_CHANNEL_ESTABLISCHMENT_FAILED, ex.getMessage());
throw new InvalidTCTokenElement(refreshUrlAsUrl.toString(), ex);
} catch (IOException | ResourceException | InvalidAddressException | ValidationError | URISyntaxException ex1) {
String errorUrl = token.getComErrorAddressWithParams(ResultMinor.COMMUNICATION_ERROR);
throw new InvalidTCTokenElement(errorUrl, INVALID_REFRESH_ADDRESS, ex1);
}
} else {
String errorUrl = token.getComErrorAddressWithParams(ResultMinor.COMMUNICATION_ERROR);
throw new InvalidTCTokenElement(errorUrl, NO_REFRESH_ADDRESS);
}
}
Aggregations