summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2021-04-19 09:23:41 +0000
committerThomas Lenz <thomas.lenz@egiz.gv.at>2021-04-19 09:23:41 +0000
commit9e072b7105c4353ea4a193e03efd00f2f63d824c (patch)
tree8d0cbfe50fc41ed592ec1b42b83c0c6cae6bbd44
parent2725ea4a3412a97a8f7ff7031f69970a8382423d (diff)
parent3e734a0f1fedba00e594bd69e72bd2f18a0a60bf (diff)
downloadEAAF-Components-9e072b7105c4353ea4a193e03efd00f2f63d824c.tar.gz
EAAF-Components-9e072b7105c4353ea4a193e03efd00f2f63d824c.tar.bz2
EAAF-Components-9e072b7105c4353ea4a193e03efd00f2f63d824c.zip
Merge branch 'feature/VT-21-016' into 'nightlyBuild'
Use custom SSLContext builder to generate BouncyCastle specific TrustManager... See merge request egiz/eaaf_components!23
-rw-r--r--eaaf_core/checks/spotbugs-exclude.xml6
-rw-r--r--eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ErrorTicketService.java243
-rw-r--r--eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java92
-rw-r--r--eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java337
-rw-r--r--eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java125
-rw-r--r--eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java12
-rw-r--r--eaaf_core_utils/pom.xml17
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/EaafSslContextBuilder.java433
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpUtils.java22
-rw-r--r--eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryProdHostTest.java98
-rw-r--r--eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryTest.java96
-rw-r--r--eaaf_core_utils/src/test/resources/data/hsm_ee-RSA_rootcert.crt3
-rw-r--r--eaaf_core_utils/src/test/resources/data/hsm_ee_eecert.crt3
-rw-r--r--eaaf_core_utils/src/test/resources/data/hsm_ee_rootcert.crt3
-rw-r--r--eaaf_core_utils/src/test/resources/data/server_host.crt18
-rw-r--r--eaaf_core_utils/src/test/resources/data/ssL_truststore.jksbin0 -> 799 bytes
-rw-r--r--eaaf_core_utils/src/test/resources/data/ssl_host.jksbin0 -> 2081 bytes
-rw-r--r--pom.xml6
18 files changed, 1288 insertions, 226 deletions
diff --git a/eaaf_core/checks/spotbugs-exclude.xml b/eaaf_core/checks/spotbugs-exclude.xml
index d1cc43e3..70f27b81 100644
--- a/eaaf_core/checks/spotbugs-exclude.xml
+++ b/eaaf_core/checks/spotbugs-exclude.xml
@@ -19,6 +19,12 @@
<Bug pattern="SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" />
</Match>
<Match>
+ <!-- the ErrorToken is only single-used as same as a CSRF token -->
+ <Class name="at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController"/>
+ <Method name="errorRedirect" />
+ <Bug pattern="SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" />
+ </Match>
+ <Match>
<!-- Only used to evaluate expressions from pre-compiled process-flows -->
<OR>
<Class name="at.gv.egiz.eaaf.core.impl.idp.process.springweb.SpringWebExpressionEvaluator"/>
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ErrorTicketService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ErrorTicketService.java
new file mode 100644
index 00000000..0834aa27
--- /dev/null
+++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ErrorTicketService.java
@@ -0,0 +1,243 @@
+package at.gv.egiz.eaaf.core.impl.idp.auth.services;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.text.StringEscapeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.IStatusMessenger;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController;
+import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
+import at.gv.egiz.eaaf.core.impl.utils.ServletUtils;
+import lombok.Getter;
+
+@Service()
+public class ErrorTicketService {
+ private static final Logger log = LoggerFactory.getLogger(ErrorTicketService.class);
+
+ private static final String CONFIG_PROP_ERRORHANDLING_ACTION_PATH = "core.errorhandling.action";
+ private static final String TECH_LOG_MSG = "errorCode={} Message={}";
+ private static final String TICKET_LOG_MSG = "Ticket={} errorCode={} Message={}";
+
+ private final HashMap<String, String> propertyMap = new HashMap<String, String>();
+
+
+ public enum ActionType {
+ TICKET_REDIRECT("ticket_redirect"), TICKET_NOREDIRECT("ticket_noredirect"), NOTICKET_REDIRECT(
+ "noticket_redirect"), NOTICKET_NOREDIRECT("noticket_noredirect"), NOTICKET_AUTOREDIRECT(
+ "noticket_autoredirect");
+
+ private final String name;
+
+ ActionType(final String text) {
+ this.name = text;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ @Autowired(required = true)
+ IConfiguration basicConfig;
+ @Autowired(required = true)
+ ResourceLoader resourceLoader;
+
+ @PostConstruct
+ private void initialize() throws EaafException {
+ log.info("initErrorTicketService");
+
+ final String ticketConfPath = basicConfig.getBasicConfiguration(CONFIG_PROP_ERRORHANDLING_ACTION_PATH);
+ log.info("ticketConfPath" + ticketConfPath);
+
+
+ if (StringUtils.isEmpty(ticketConfPath)) {
+ log.error("Error: Path to errorhandling-action mapping not known");
+ throw new EaafException("internal.configuration.00",
+ new Object[]{CONFIG_PROP_ERRORHANDLING_ACTION_PATH});
+ } else {
+
+ Properties getProperties = new Properties();
+ String fullFilePath = null;
+ try {
+
+ fullFilePath = FileUtils
+ .makeAbsoluteUrl(ticketConfPath, basicConfig.getConfigurationRootDirectory());
+ final Resource ressource = resourceLoader.getResource(fullFilePath);
+ final InputStream is = ressource.getInputStream();
+ getProperties.load(is);
+ is.close();
+ propertyMap.putAll((Map) getProperties);
+
+ // log.error(propertyMap.toString());
+ // log.error("working: " + propertyMap.get("auth.00"));
+
+ } catch (Exception e) {
+ log.error("Error: could not found file.", e);
+ throw new EaafException("internal.configuration.01",
+ new Object[]{CONFIG_PROP_ERRORHANDLING_ACTION_PATH, "File for errorhandling-action mapping cloud "
+ + "not be found."});
+ }
+ }
+ }
+
+ /**
+ * creates error handling data.
+ * @param throwable error
+ * @param req http request
+ * @return eror handle Data
+ * @throws EaafException In case of an internal error
+ */
+ public HandleData createHandleData(Throwable throwable, HttpServletRequest req) throws EaafException {
+ HandleData data = new HandleData(throwable, req);
+ extractErrorCode(data);
+ setUpErrorData(data);
+
+ return data;
+ }
+
+ private void extractErrorCode(HandleData data) {
+ Throwable originalException;
+ if (data.throwable instanceof TaskExecutionException
+ && ((TaskExecutionException) data.throwable).getOriginalException() != null) {
+ originalException = ((TaskExecutionException) data.throwable).getOriginalException();
+
+ } else {
+ originalException = data.throwable;
+
+ }
+
+ if (!(originalException instanceof EaafException)) {
+ data.errorCode = IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC;
+
+ } else {
+ data.errorCode = ((EaafException) originalException).getErrorId();
+
+ }
+ }
+
+ private void setUpErrorData(HandleData data) throws EaafException {
+
+ if (propertyMap.containsKey(data.errorCode)) {
+ String action = propertyMap.get(data.errorCode);
+
+ if (action.equals(ActionType.TICKET_REDIRECT.toString())) {
+ data.actionType = ActionType.TICKET_REDIRECT;
+ data.generateSupportTicket();
+ data.generateRedirect();
+
+ } else if (action.equals(ActionType.TICKET_NOREDIRECT.toString())) {
+ data.actionType = ActionType.TICKET_NOREDIRECT;
+ data.generateSupportTicket();
+
+ } else if (action.equals(ActionType.NOTICKET_REDIRECT.toString())) {
+ data.actionType = ActionType.NOTICKET_REDIRECT;
+ data.generateRedirect();
+
+ } else if (action.equals(ActionType.NOTICKET_AUTOREDIRECT.toString())) {
+ data.actionType = ActionType.NOTICKET_AUTOREDIRECT;
+
+ } else { // ActionType.NOTICKET_NOREDIRECT -> nothing to be done
+ data.actionType = ActionType.NOTICKET_NOREDIRECT;
+
+ }
+
+ } else {
+ data.generateSupportTicket();
+ throw new EaafException("internal.configuration.00",
+ new Object[]{data.errorCode + " in on_error_action" + ".properties"});
+ }
+ }
+
+ static class HandleData {
+ private final HttpServletRequest req;
+ @Getter
+ private String supportTicket;
+ @Getter
+ private String redirectUrl;
+ @Getter
+ private final Throwable throwable;
+ @Getter
+ private String errorCode;
+ @Getter
+ private ActionType actionType;
+
+
+ private HandleData(Throwable throwable, HttpServletRequest req) {
+ this.throwable = throwable;
+ this.req = req;
+ }
+
+ private void generateRedirect() {
+ redirectUrl = ServletUtils.getBaseUrl(req);
+ redirectUrl +=
+ ProtocolFinalizationController.ENDPOINT_ERROR_REDIRECT + "?" + EaafConstants.PARAM_HTTP_ERROR_CODE + "="
+ + StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE));
+
+ }
+
+ private void generateSupportTicket() {
+
+ String randomCode =
+ RandomStringUtils.randomAlphanumeric(4).toUpperCase() + '-' + RandomStringUtils.randomAlphanumeric(4)
+ .toUpperCase() + '-' + RandomStringUtils.randomAlphanumeric(4).toUpperCase();
+ supportTicket = randomCode;
+ }
+
+ /**
+ * Logs error to technical log.
+ */
+ public void log_error() {
+
+ if (supportTicket != null) {
+ log.error(TICKET_LOG_MSG, supportTicket, errorCode, throwable.getMessage(), throwable);
+ } else {
+ log.error(TECH_LOG_MSG, errorCode, throwable.getMessage(), throwable);
+ }
+ }
+
+ /**
+ * Logs info to technical log.
+ */
+ public void log_info() {
+
+ if (supportTicket != null) {
+ log.info(TICKET_LOG_MSG, supportTicket, errorCode, throwable.getMessage(), throwable);
+
+ } else {
+ log.info(TECH_LOG_MSG, errorCode, throwable.getMessage(), throwable);
+ }
+ }
+
+ /**
+ * Logs warn to technical log.
+ */
+ public void log_warn() {
+
+ if (supportTicket != null) {
+ log.warn(TICKET_LOG_MSG, supportTicket, errorCode, throwable.getMessage(), throwable);
+
+ } else {
+ log.warn(TECH_LOG_MSG, errorCode, throwable.getMessage(), throwable);
+ }
+ }
+ }
+}
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java
new file mode 100644
index 00000000..812a5171
--- /dev/null
+++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java
@@ -0,0 +1,92 @@
+package at.gv.egiz.eaaf.core.impl.idp.auth.services;
+
+import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashSet;
+
+public interface IErrorService {
+ /**
+ * Describes the kind of action that should be taken.
+ */
+ enum ActionType {
+ TICKET_REDIRECT("ticket_redirect"), TICKET_NOREDIRECT("ticket_noredirect"), NOTICKET_REDIRECT(
+ "noticket_redirect"), NOTICKET_NOREDIRECT("noticket_noredirect"), NOTICKET_AUTOREDIRECT(
+ "noticket_autoredirect");
+
+ private final String name;
+
+ ActionType(final String text) {
+ this.name = text;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ String PARAM_GUI_TICKET = "supportTicket";
+ String PARAM_GUI_REDIRECT = "redirectLink";
+
+ /**
+ * Maps internal error codes to external ones.
+ * @param internalCode internal error code
+ * @return external error code
+ */
+ String getExternalCodeFromInternal(String internalCode);
+
+ /**
+ * creates error handling data.
+ *
+ * @param throwable error
+ * @param req http request
+ * @return eror handle Data
+ * @throws EaafException In case of an internal error
+ */
+ IHandleData createHandleData(Throwable throwable, HttpServletRequest req) throws EaafException;
+
+ /**
+ * Displays the error using suitable errordata.
+ *
+ * @param c guibuilder
+ * @param errorData Data to handle
+ * @throws EaafException In case of an internal error
+ */
+ void displayErrorData(ModifyableGuiBuilderConfiguration c, IErrorService.IHandleData errorData)
+ throws EaafException;
+
+ /**
+ * Contains all the Model data for Error Handling.
+ */
+ interface IHandleData {
+ /**
+ * Describes the kind of action that should be taken.
+ *
+ * @return The appropriate action
+ */
+ ActionType getActionType();
+
+ /**
+ * Get internal errorCode describing the problem.
+ *
+ * @return internal error Code.
+ */
+ String getInternalErrorCode();
+
+ /**
+ * Get the original throwable of the error.
+ *
+ * @return causing throwable
+ */
+ Throwable getThrowable();
+
+ /**
+ * Write a Exception to the MOA-ID-Auth internal technical log.
+ *
+ * @param logOnInfoLevel set of what to log on info logging lvl
+ */
+ void logExceptionToTechnicalLog(HashSet<String> logOnInfoLevel);
+ }
+}
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java
index abb3d685..a64ad45e 100644
--- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java
+++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java
@@ -15,7 +15,7 @@
* This product combines work with different licenses. See the "NOTICE" text file for details on the
* various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
* works that you distribute must include a readable copy of the "NOTICE" text file.
-*/
+ */
package at.gv.egiz.eaaf.core.impl.idp.auth.services;
@@ -38,12 +38,14 @@ import org.springframework.context.ApplicationContext;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
+import org.springframework.util.SerializationUtils;
import at.gv.egiz.components.eventlog.api.EventConstants;
import at.gv.egiz.eaaf.core.api.IRequest;
import at.gv.egiz.eaaf.core.api.IRequestStorage;
import at.gv.egiz.eaaf.core.api.IStatusMessenger;
import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ExceptionContainer;
import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration;
import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfigurationFactory;
import at.gv.egiz.eaaf.core.api.gui.IGuiFormBuilder;
@@ -60,6 +62,7 @@ import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService
import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface;
import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;
import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger;
+import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;
import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy;
import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;
import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
@@ -69,7 +72,6 @@ import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;
import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException;
import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException;
import at.gv.egiz.eaaf.core.exceptions.ProtocolNotActiveException;
-import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
import at.gv.egiz.eaaf.core.impl.data.Pair;
import at.gv.egiz.eaaf.core.impl.gui.AbstractGuiFormBuilderConfiguration;
import at.gv.egiz.eaaf.core.impl.http.HttpUtils;
@@ -78,13 +80,14 @@ import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
import at.gv.egiz.eaaf.core.impl.utils.ServletUtils;
+
+
+
@Service
public class ProtocolAuthenticationService implements IProtocolAuthenticationService {
private static final Logger log = LoggerFactory.getLogger(ProtocolAuthenticationService.class);
- private static final String CONFIG_PROP_LOGGER_ON_INFO_LEVEL =
- "core.logging.level.info.errorcodes";
- private static final String TECH_LOG_MSG = "errorCode={} Message={}";
+ private static final String CONFIG_PROP_LOGGER_ON_INFO_LEVEL = "core.logging.level.info.errorcodes";
@Autowired(required = true)
private ApplicationContext applicationContext;
@@ -100,15 +103,28 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
private IRequestStorage requestStorage;
@Autowired(required = true)
IPendingRequestIdGenerationStrategy pendingReqIdGenerationStrategy;
- @Autowired private IConfiguration basicConfig;
+ @Autowired
+ private IConfiguration basicConfig;
+
+ @Autowired(required = true)
+ private IErrorService errorTicketService;
@Autowired(required = false)
private ISsoManager ssoManager;
+
@Autowired
private IStatisticLogger statisticLogger;
+
@Autowired
private IRevisionLogger revisionsLogger;
+ @Autowired(required = true)
+ protected ITransactionStorage transactionStorage;
+
+ @Autowired
+ IPendingRequestIdGenerationStrategy requestIdValidationStragegy;
+
+
private IGuiFormBuilder guiBuilder;
private final HashSet<String> logOnInfoLevel = new HashSet<>();
@@ -136,9 +152,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
final ISpConfiguration oaParam = pendingReq.getServiceProviderConfiguration();
if (oaParam == null) {
- throw new EaafAuthenticationException(
- IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG,
- new Object[] { pendingReq.getSpEntityId() });
+ throw new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG,
+ new Object[]{pendingReq.getSpEntityId()});
}
if (authmanager.doAuthentication(req, resp, pendingReq)) {
@@ -148,8 +163,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
finalizeAuthentication(req, resp, pendingReq);
// transaction is finished, log transaction finished event
- revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED,
- pendingReq.getUniqueTransactionIdentifier());
+ revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier());
}
@@ -183,9 +197,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
if (pendingReq.isAbortedByUser()) {
// send authentication aborted error to Service Provider
buildProtocolSpecificErrorResponse(
- new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP,
- new Object[] {}),
- req, resp, pendingReq);
+ new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP, new Object[]{}), req,
+ resp, pendingReq);
// check if pending-request are authenticated
} else if (pendingReq.isAuthenticated() && !pendingReq.isNeedUserConsent()) {
@@ -193,11 +206,10 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
} else {
// suspect state: pending-request is not aborted but also are not authenticated
- log.warn("PendingRequest flag for 'authenticated':{} and 'needConsent':{}",
- pendingReq.isAuthenticated(), pendingReq.isNeedUserConsent());
+ log.warn("PendingRequest flag for 'authenticated':{} and 'needConsent':{}", pendingReq.isAuthenticated(),
+ pendingReq.isNeedUserConsent());
if (pendingReq.isNeedUserConsent()) {
- log.error(
- "PendingRequest NEEDS user-consent. "
+ log.error("PendingRequest NEEDS user-consent. "
+ "Can NOT fininalize authentication --> Abort authentication process!");
} else {
@@ -216,58 +228,97 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
} finally {
// remove pending-request
requestStorage.removePendingRequest(pendingReq.getPendingRequestId());
- revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED,
- pendingReq.getUniqueTransactionIdentifier());
+ revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier());
}
}
+
@Override
- public void buildProtocolSpecificErrorResponse(final Throwable throwable,
- final HttpServletRequest req, final HttpServletResponse resp, final IRequest protocolRequest)
- throws EaafException, IOException {
+ public void buildProtocolSpecificErrorResponse(final Throwable throwable, final HttpServletRequest req,
+ final HttpServletResponse resp, final IRequest protocolRequest) throws EaafException, IOException {
try {
+ IErrorService.IHandleData errorData = errorTicketService.createHandleData(throwable, req);
+
+ if (errorData.getActionType().equals(IErrorService.ActionType.TICKET_REDIRECT) || errorData.getActionType()
+ .equals(IErrorService.ActionType.NOTICKET_REDIRECT)) {
- final Class<?> clazz = Class.forName(protocolRequest.requestedModule());
+ // Put pending request
+ ExceptionContainer exceptionContainer = new ExceptionContainer(protocolRequest, throwable);
+ byte[] serialized = SerializationUtils.serialize(exceptionContainer);
+ // transactionStorage.put(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE), serialized, -1);
+ String errorId = requestIdValidationStragegy
+ .validateAndGetPendingRequestId(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE));
+ transactionStorage.put(errorId, serialized, -1);
- if (clazz == null || !IModulInfo.class.isAssignableFrom(clazz)) {
- log.error(
- "Requested protocol module Class is NULL or does not implement the IModulInfo interface.");
- throw new ClassCastException(
- "Requested protocol module Class is NULL or does not implement the IModulInfo interface.");
+ // log Error to technical log
+ errorData.logExceptionToTechnicalLog(logOnInfoLevel);
- }
+ // log Error Message
+ statisticLogger.logErrorOperation(throwable, protocolRequest);
- final IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz);
+ displayException(req, resp, errorData);
- if (handlingModule.generateErrorMessage(throwable, req, resp, protocolRequest)) {
+ } else if (errorData.getActionType().equals(IErrorService.ActionType.NOTICKET_AUTOREDIRECT)) {
+ IModulInfo handlingModule = extractShibbolethHandling(protocolRequest, applicationContext);
- // log Error to technical log
- logExceptionToTechnicalLog(throwable);
+ if (handlingModule.generateErrorMessage(throwable, req, resp, protocolRequest)) {
- // log Error Message
- statisticLogger.logErrorOperation(throwable, protocolRequest);
+ // log Error to technical log
+ errorData.logExceptionToTechnicalLog(logOnInfoLevel);
+
+ // log Error Message
+ statisticLogger.logErrorOperation(throwable, protocolRequest);
+
+ // write revision log entries
+ revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR,
+ protocolRequest.getUniqueTransactionIdentifier());
- // write revision log entries
- revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR,
- protocolRequest.getUniqueTransactionIdentifier());
+ } else {
+ throw throwable; //through it on to handleErrorNoRedirect
+
+ }
} else {
- handleErrorNoRedirect(throwable, req, resp, true);
+ throw throwable; //through it on to handleErrorNoRedirect
}
} catch (final Throwable e) {
- handleErrorNoRedirect(throwable, req, resp, true);
-
+ // if building error response results in error, we try with with handleErrorNoRedirect
+ handleErrorNoRedirect(e, req, resp, true);
}
+ }
+ /**
+ * Retrieves shibboleth module info.
+ *
+ * @param protocolRequest current request
+ * @param applicationContext spring context
+ * @return IModulInfo
+ * @throws ClassNotFoundException If no shibboleth handling implementation found
+ */
+ public static IModulInfo extractShibbolethHandling(IRequest protocolRequest, ApplicationContext applicationContext)
+ throws ClassNotFoundException {
+ final Class<?> clazz = Class.forName(protocolRequest.requestedModule());
+
+ if (clazz == null || !IModulInfo.class.isAssignableFrom(clazz)) {
+ log.error("Requested protocol module Class is NULL or does not implement the IModulInfo interface.");
+ throw new ClassCastException(
+ "Requested protocol module Class is NULL or does not implement the IModulInfo interface.");
+
+ }
+
+ return (IModulInfo) applicationContext.getBean(clazz);
}
+
@Override
public void handleErrorNoRedirect(final Throwable throwable, final HttpServletRequest req,
- final HttpServletResponse resp, final boolean writeExceptionToStatisticLog)
- throws IOException, EaafException {
+ final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) throws EaafException, IOException {
+
+ IErrorService.IHandleData errorData = null;
+ errorData = errorTicketService.createHandleData(throwable, req);
// log Exception into statistic database
if (writeExceptionToStatisticLog) {
@@ -275,30 +326,25 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
}
// write errror to console
- logExceptionToTechnicalLog(throwable);
-
- // return error to Web browser
- if (throwable instanceof EaafException || throwable instanceof ProcessExecutionException) {
- internalMoaidExceptionHandler(req, resp, (Exception) throwable, false);
+ errorData.logExceptionToTechnicalLog(logOnInfoLevel);
+ if (errorData.getActionType().equals(IErrorService.ActionType.NOTICKET_NOREDIRECT) || errorData
+ .getActionType().equals(IErrorService.ActionType.TICKET_NOREDIRECT)) {
+ // return error to Web browser
+ displayException(req, resp, errorData);
} else {
- // write generic message for general exceptions
- final String msg =
- statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null);
- final String internalErrorCode = statusMessager.getResponseErrorCode(throwable);
-
- writeHtmlErrorResponse(req, resp, msg, internalErrorCode, null,
- statusMessager.mapInternalErrorToExternalError(internalErrorCode));
-
+ // TODO introduce separate error type?
+ throw new EaafException("internal.configuration.01", new Object[]{
+ errorData.getInternalErrorCode() + " in on_error_action" + ".properties", "Erroraction mapping mismatch"});
}
-
}
+
@Override
public void forwardToErrorHandler(Pair<IRequest, Throwable> errorToHandle, String errorKey,
final HttpServletRequest req, final HttpServletResponse resp) throws GuiBuildException {
- final IGuiBuilderConfiguration parentHopGuiConfig =
- evaluateRequiredErrorHandlingMethod(errorToHandle.getFirst(), errorKey);
+ final IGuiBuilderConfiguration parentHopGuiConfig = evaluateRequiredErrorHandlingMethod(errorToHandle.getFirst(),
+ errorKey);
if (parentHopGuiConfig != null) {
log.trace("iFrame to parent hop requested. Building GUI step for error handling ... ");
guiBuilder.build(req, resp, parentHopGuiConfig, "iFrame-to-parent");
@@ -321,15 +367,13 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
/**
* Finalize the requested protocol operation.
*
- * @param httpReq HttpServletRequest
- * @param httpResp HttpServletResponse
- * @param protocolRequest Authentication request which is actually in process
- * @param moaSession MOASession object, which is used to generate the
- * protocol specific authentication information
+ * @param req HttpServletRequest
+ * @param resp HttpServletResponse
+ * @param pendingReq Authentication request which is actually in process
* @throws Exception In case of an error
*/
- protected void internalFinalizeAuthenticationProcess(final HttpServletRequest req,
- final HttpServletResponse resp, final IRequest pendingReq) throws Exception {
+ protected void internalFinalizeAuthenticationProcess(final HttpServletRequest req, final HttpServletResponse resp,
+ final IRequest pendingReq) throws Exception {
String newSsoSessionId = null;
@@ -351,8 +395,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
final IAuthData authData = authDataBuilder.buildAuthenticationData(pendingReq);
// execute the protocol-specific action
- final SloInformationInterface sloInformation =
- executeProtocolSpecificAction(req, resp, pendingReq, authData);
+ final SloInformationInterface sloInformation = executeProtocolSpecificAction(req, resp, pendingReq, authData);
// Store OA specific SSO session information if an SSO cookie is set
if (StringUtils.isNotEmpty(newSsoSessionId)) {
@@ -372,52 +415,15 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
}
// Advanced statistic logging
- statisticLogger.logSuccessOperation(pendingReq, authData,
- StringUtils.isNotEmpty(newSsoSessionId));
+ statisticLogger.logSuccessOperation(pendingReq, authData, StringUtils.isNotEmpty(newSsoSessionId));
}
- /**
- * Write a Exception to the MOA-ID-Auth internal technical log.
- *
- * @param loggedException Exception to log
- */
- protected void logExceptionToTechnicalLog(final Throwable loggedException) {
- // In case of a TaskExecutionException, which is only a container for process-errors,
- // extract internal exception
- Throwable toLog;
- if (loggedException instanceof TaskExecutionException
- && ((TaskExecutionException)loggedException).getOriginalException() != null) {
- toLog = ((TaskExecutionException)loggedException).getOriginalException();
-
- } else {
- toLog = loggedException;
-
- }
-
- // Log exception
- if (!(toLog instanceof EaafException)) {
- log.error(TECH_LOG_MSG, IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC,
- toLog.getMessage(), toLog);
-
- } else {
- if (logOnInfoLevel.contains(((EaafException) toLog).getErrorId())) {
- log.info(TECH_LOG_MSG, ((EaafException) toLog).getErrorId(),
- toLog.getMessage(), toLog);
-
- } else {
- log.warn(TECH_LOG_MSG, ((EaafException) toLog).getErrorId(),
- toLog.getMessage(), toLog);
-
- }
- }
- }
-
@PostConstruct
private void initializer() {
log.trace("Initializing {} ...", ProtocolAuthenticationService.class.getName());
- logOnInfoLevel.addAll(KeyValueUtils.getListOfCsvValues(
- basicConfig.getBasicConfiguration(CONFIG_PROP_LOGGER_ON_INFO_LEVEL)));
+ logOnInfoLevel
+ .addAll(KeyValueUtils.getListOfCsvValues(basicConfig.getBasicConfiguration(CONFIG_PROP_LOGGER_ON_INFO_LEVEL)));
log.info("Set errorCodes={} to LogLevel:INFO", String.join(",", logOnInfoLevel));
}
@@ -425,24 +431,20 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
/**
* Executes the requested protocol action.
*
- * @param httpReq HttpServletRequest
- * @param httpResp HttpServletResponse
- * @param protocolRequest Authentication request which is actually in process
- * @param authData Service-provider specific authentication data
- *
+ * @param httpReq HttpServletRequest
+ * @param httpResp HttpServletResponse
+ * @param pendingReq Authentication request which is actually in process
+ * @param authData Service-provider specific authentication data
* @return Return Single LogOut information or null if protocol supports no SSO
- *
* @throws Exception in case of an error
*/
private SloInformationInterface executeProtocolSpecificAction(final HttpServletRequest httpReq,
- final HttpServletResponse httpResp, final IRequest pendingReq, final IAuthData authData)
- throws Exception {
+ final HttpServletResponse httpResp, final IRequest pendingReq, final IAuthData authData) throws Exception {
try {
// request needs no authentication --> start request processing
final Class<?> clazz = Class.forName(pendingReq.requestedAction());
if (clazz == null || !IAction.class.isAssignableFrom(clazz)) {
- log.error(
- "Requested protocol-action processing Class is NULL or does not implement the IAction interface.");
+ log.error("Requested protocol-action processing Class is NULL or does not implement the IAction interface.");
throw new ClassCastException(
"Requested protocol-action processing Class is NULL or does not implement the IAction interface.");
@@ -452,25 +454,33 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
return protocolAction.processRequest(pendingReq, httpReq, httpResp, authData);
} catch (final ClassNotFoundException e) {
- log.error(
- "Requested Auth. protocol processing Class is NULL or does not implement the IAction interface.");
+ log.error("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface.");
throw new ClassNotFoundException(
"Requested Auth. protocol processing Class is NULL or does not implement the IAction interface.", e);
}
}
+
+ // private void writeHtmlErrorResponse(@NonNull final HttpServletRequest httpReq,
+ // @NonNull final HttpServletResponse httpResp, @NonNull final String msg, @NonNull final String errorCode,
+ // @Nullable final Object[] params, String externalErrorCode) throws EaafException {
+ // this.writeHtmlErrorResponse(httpReq, httpResp, msg, errorCode, params, externalErrorCode, null, null);
+ // }
+
+
private void writeHtmlErrorResponse(@NonNull final HttpServletRequest httpReq,
- @NonNull final HttpServletResponse httpResp, @NonNull final String msg,
- @NonNull final String errorCode, @Nullable final Object[] params, String externalErrorCode) throws EaafException {
+ @NonNull final HttpServletResponse httpResp, @NonNull final String msg, @NonNull final String errorCode,
+ @Nullable final Object[] params, String externalErrorCode, IErrorService.IHandleData errorData)
+ throws EaafException {
try {
- final IGuiBuilderConfiguration config =
- guiConfigFactory.getDefaultErrorGui(HttpUtils.extractAuthUrlFromRequest(httpReq));
+ final IGuiBuilderConfiguration config = guiConfigFactory
+ .getDefaultErrorGui(HttpUtils.extractAuthUrlFromRequest(httpReq));
String[] errorCodeParams = null;
if (params == null) {
- errorCodeParams = new String[] {};
+ errorCodeParams = new String[]{};
} else {
errorCodeParams = new String[params.length];
for (int i = 0; i < params.length; i++) {
@@ -485,20 +495,19 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
// add errorcode and errormessage
if (config instanceof ModifyableGuiBuilderConfiguration) {
- ((ModifyableGuiBuilderConfiguration) config).putCustomParameter(
- AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERROMSG, msg);
- ((ModifyableGuiBuilderConfiguration) config).putCustomParameter(
- AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODE, errorCode);
- ((ModifyableGuiBuilderConfiguration) config).putCustomParameter(
- AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_EXTERNAL_ERRORCODE,
- externalErrorCode);
- ((ModifyableGuiBuilderConfiguration) config).putCustomParameterWithOutEscaption(
- AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODEPARAMS,
- ArrayUtils.toString(errorCodeParams));
+ ModifyableGuiBuilderConfiguration c = (ModifyableGuiBuilderConfiguration) config;
+ c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERROMSG, msg);
+ c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODE, errorCode);
+ // TODO: should we keep the internal errorcode secret?
+ c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_EXTERNAL_ERRORCODE,
+ externalErrorCode);
+ c.putCustomParameterWithOutEscaption(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG,
+ PARAM_GUI_ERRORCODEPARAMS, ArrayUtils.toString(errorCodeParams));
+ errorTicketService.displayErrorData(c, errorData);
+
} else {
- log.info(
- "Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable ");
+ log.info("Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable ");
}
guiBuilder.build(httpReq, httpResp, config, "Error-Message");
@@ -511,60 +520,44 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer
}
- private void internalMoaidExceptionHandler(final HttpServletRequest req,
- final HttpServletResponse resp, final Exception e, final boolean writeExceptionToStatisicLog)
- throws IOException, EaafException {
- final String internalErrorCode = statusMessager.getResponseErrorCode(e);
-
+ private void displayException(final HttpServletRequest req, final HttpServletResponse resp,
+ final IErrorService.IHandleData errorData) throws IOException, EaafException {
+ final Throwable e = errorData.getThrowable();
+ final String internalErrorCode = errorData.getInternalErrorCode();
+
+ // send error response
if (e instanceof ProtocolNotActiveException) {
resp.getWriter().write(Encode.forHtml(e.getMessage()));
resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8);
resp.sendError(HttpServletResponse.SC_FORBIDDEN,
StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage())));
- } else if (e instanceof AuthnRequestValidatorException) {
- final AuthnRequestValidatorException ex = (AuthnRequestValidatorException) e;
- // log Error Message
- if (writeExceptionToStatisicLog) {
- statisticLogger.logErrorOperation(ex, ex.getErrorRequest());
- }
-
+ } else if (e instanceof AuthnRequestValidatorException || e instanceof InvalidProtocolRequestException
+ || e instanceof ProcessExecutionException || e instanceof ConfigurationException) {
// write error message
writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, null,
- statusMessager.mapInternalErrorToExternalError(internalErrorCode));
-
- } else if (e instanceof InvalidProtocolRequestException) {
- // send error response
- writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, null,
- statusMessager.mapInternalErrorToExternalError(internalErrorCode));
-
- } else if (e instanceof ConfigurationException) {
- // send HTML formated error message
- writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, null,
- statusMessager.mapInternalErrorToExternalError(internalErrorCode));
+ statusMessager.mapInternalErrorToExternalError(internalErrorCode), errorData);
} else if (e instanceof EaafException) {
// send HTML formated error message
- writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode,
- ((EaafException) e).getParams(), statusMessager.mapInternalErrorToExternalError(internalErrorCode));
+ writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, ((EaafException) e).getParams(),
+ statusMessager.mapInternalErrorToExternalError(internalErrorCode), errorData);
- } else if (e instanceof ProcessExecutionException) {
- // send HTML formated error message
- writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, null,
- statusMessager.mapInternalErrorToExternalError(internalErrorCode));
+ } else {
+ // write generic message for general exceptions
+ final String msg = statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null);
+ writeHtmlErrorResponse(req, resp, msg, internalErrorCode, null,
+ statusMessager.mapInternalErrorToExternalError(internalErrorCode), errorData);
}
-
}
private IGuiBuilderConfiguration evaluateRequiredErrorHandlingMethod(IRequest first, String errorId) {
if (first != null && first.isProcessInIframe()) {
- return guiConfigFactory.getDefaultIFrameParentHopGui(first,
- ProtocolFinalizationController.ENDPOINT_ERRORHANDLING,
- errorId);
+ return guiConfigFactory
+ .getDefaultIFrameParentHopGui(first, "/" + ProtocolFinalizationController.ENDPOINT_ERRORHANDLING, errorId);
}
-
return null;
}
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java
index b2130fb4..a8b0a961 100644
--- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java
+++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java
@@ -15,7 +15,7 @@
* This product combines work with different licenses. See the "NOTICE" text file for details on the
* various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
* works that you distribute must include a readable copy of the "NOTICE" text file.
-*/
+ */
package at.gv.egiz.eaaf.core.impl.idp.controller;
@@ -39,15 +39,16 @@ import at.gv.egiz.eaaf.core.api.IRequestStorage;
import at.gv.egiz.eaaf.core.api.IStatusMessenger;
import at.gv.egiz.eaaf.core.api.data.EaafConstants;
import at.gv.egiz.eaaf.core.api.data.ExceptionContainer;
+import at.gv.egiz.eaaf.core.api.idp.IModulInfo;
import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy;
import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.services.ProtocolAuthenticationService;
import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils;
/**
* Protocol finialization end-point.
*
* @author tlenz
- *
*/
@Controller
public class ProtocolFinalizationController extends AbstractController {
@@ -56,10 +57,72 @@ public class ProtocolFinalizationController extends AbstractController {
EaafConstants.ENDPOINT_PREFIX_SECURED + "/finalizeAuthProtocol";
public static final String ENDPOINT_ERRORHANDLING =
EaafConstants.ENDPOINT_PREFIX_SECURED + "/errorHandling";
+ public static final String ENDPOINT_ERROR_REDIRECT =
+ EaafConstants.ENDPOINT_PREFIX_SECURED + "/errorRedirect";
@Autowired(required = true)
IRequestStorage requestStorage;
- @Autowired IPendingRequestIdGenerationStrategy requestIdValidationStragegy;
+ @Autowired
+ IPendingRequestIdGenerationStrategy requestIdValidationStragegy;
+
+
+ /**
+ * Handles incoming requests for redirects to IDP.
+ * @param req http request
+ * @param resp http response
+ * @throws EaafException In case of an internal error
+ * @throws IOException In case of a servlet error
+ */
+ @RequestMapping(value = ENDPOINT_ERROR_REDIRECT, method = {RequestMethod.GET, RequestMethod.POST})
+ public void errorRedirect(final HttpServletRequest req, final HttpServletResponse resp)
+ throws EaafException, IOException {
+
+ final String errorToken = StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE));
+ if (errorToken != null) {
+ IRequest pendingReq = null;
+ try {
+ String errorId = requestIdValidationStragegy.validateAndGetPendingRequestId(errorToken);
+ log.debug("Searching exception with internal error-token: {}", errorId);
+
+ // load stored exception from database
+ final byte[] containerSerialized = transactionStorage.get(errorId, byte[].class);
+ if (containerSerialized != null) {
+ // remove exception if it was found
+ transactionStorage.remove(errorId);
+ log.trace("Find exception with internal error-token: {}", errorId);
+
+ //final Object containerObj = EaafSerializationUtils.deserialize(containerSerialized,
+ // Arrays.asList(
+ // ExceptionContainer.class.getName()
+ // ));
+ final Object containerObj = SerializationUtils.deserialize(containerSerialized);
+
+ if (containerObj instanceof ExceptionContainer) {
+ final ExceptionContainer container = (ExceptionContainer) containerObj;
+ final Throwable throwable = container.getExceptionThrown();
+ pendingReq = container.getPendingRequest();
+
+ if (pendingReq != null) {
+ IModulInfo handlingModule = ProtocolAuthenticationService
+ .extractShibbolethHandling(pendingReq, applicationContext);
+
+ handlingModule.generateErrorMessage(throwable, req, resp, pendingReq);
+ }
+ }
+ }
+ } catch (Throwable e) {
+ log.error(e.getMessage(), e);
+ protAuthService.handleErrorNoRedirect(e, req, resp, false);
+ } finally {
+ // remove pending-request
+ if (pendingReq != null) {
+ requestStorage.removePendingRequest(pendingReq.getPendingRequestId());
+ revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier());
+
+ }
+ }
+ }
+ }
/**
* End-Point to handle errors.
@@ -69,32 +132,30 @@ public class ProtocolFinalizationController extends AbstractController {
* @throws EaafException In case of an internal error
* @throws IOException In case of a servlet error
*/
- @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = { RequestMethod.GET, RequestMethod.POST })
+ @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = {RequestMethod.GET, RequestMethod.POST})
public void errorHandling(final HttpServletRequest req, final HttpServletResponse resp)
throws EaafException, IOException {
// receive an authentication error
- final String errorToken =
- StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE));
+ final String errorToken = StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE));
if (errorToken != null) {
IRequest pendingReq = null;
- try {
- String errorId = requestIdValidationStragegy.validateAndGetPendingRequestId(errorToken);
+ try {
+ String errorId = requestIdValidationStragegy.validateAndGetPendingRequestId(errorToken);
log.debug("Searching exception with internal error-token: {}", errorId);
-
+
// load stored exception from database
- final byte[] containerSerialized =
- transactionStorage.get(errorId, byte[].class);
+ final byte[] containerSerialized = transactionStorage.get(errorId, byte[].class);
if (containerSerialized != null) {
// remove exception if it was found
transactionStorage.remove(errorId);
log.trace("Find exception with internal error-token: {}", errorId);
-
+
//final Object containerObj = EaafSerializationUtils.deserialize(containerSerialized,
// Arrays.asList(
// ExceptionContainer.class.getName()
// ));
final Object containerObj = SerializationUtils.deserialize(containerSerialized);
-
+
if (containerObj instanceof ExceptionContainer) {
final ExceptionContainer container = (ExceptionContainer) containerObj;
final Throwable throwable = container.getExceptionThrown();
@@ -103,7 +164,7 @@ public class ProtocolFinalizationController extends AbstractController {
if (pendingReq != null) {
//set MDC variables
TransactionIdUtils.setAllLoggingVariables(pendingReq);
-
+
// build protocol-specific error message if possible
protAuthService.buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq);
@@ -116,17 +177,17 @@ public class ProtocolFinalizationController extends AbstractController {
}
} else {
- protAuthService.handleErrorNoRedirect(
- new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null),
- req, resp, false);
+ protAuthService
+ .handleErrorNoRedirect(new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null), req,
+ resp, false);
}
} else {
log.info("Find no exception with internal error-token: {}", errorId);
- protAuthService.handleErrorNoRedirect(
- new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null),
- req, resp, false);
+ protAuthService
+ .handleErrorNoRedirect(new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null),
+ req, resp, false);
}
@@ -138,11 +199,10 @@ public class ProtocolFinalizationController extends AbstractController {
// remove pending-request
if (pendingReq != null) {
requestStorage.removePendingRequest(pendingReq.getPendingRequestId());
- revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED,
- pendingReq.getUniqueTransactionIdentifier());
+ revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier());
}
-
+
//remove all Logger variables
TransactionIdUtils.removeAllLoggingVariables();
@@ -150,9 +210,9 @@ public class ProtocolFinalizationController extends AbstractController {
} else {
log.debug("Request contains NO ErrorId");
- protAuthService.handleErrorNoRedirect(
- new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null), req,
- resp, false);
+ protAuthService
+ .handleErrorNoRedirect(new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, null), req,
+ resp, false);
}
@@ -166,7 +226,7 @@ public class ProtocolFinalizationController extends AbstractController {
* @throws EaafException In case of an internal error
* @throws IOException In case of a servlet error
*/
- @RequestMapping(value = ENDPOINT_FINALIZEPROTOCOL, method = { RequestMethod.GET })
+ @RequestMapping(value = ENDPOINT_FINALIZEPROTOCOL, method = {RequestMethod.GET})
public void finalizeAuthProtocol(final HttpServletRequest req, final HttpServletResponse resp)
throws EaafException, IOException {
@@ -179,19 +239,18 @@ public class ProtocolFinalizationController extends AbstractController {
log.info("PendingReqId was valid but no PendingRequest with ID: {}. Looks already used",
pendingRequestID);
protAuthService.handleErrorNoRedirect(
- new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT,
- new Object[] { pendingRequestID, }),
- req, resp, false);
+ new EaafException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, new Object[]{pendingRequestID,}), req,
+ resp, false);
} else {
//set MDC variables
TransactionIdUtils.setAllLoggingVariables(pendingReq);
-
+
//perform protocol finalization steps
protAuthService.finalizeAuthentication(req, resp, pendingReq);
-
+
}
-
+
}
}
diff --git a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java
index 6580fa30..f110d50e 100644
--- a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java
+++ b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java
@@ -19,17 +19,16 @@
package at.gv.egiz.eaaf.core.api.idp.auth.services;
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
import at.gv.egiz.eaaf.core.api.IRequest;
import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger;
import at.gv.egiz.eaaf.core.exceptions.EaafException;
import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;
import at.gv.egiz.eaaf.core.impl.data.Pair;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
public interface IProtocolAuthenticationService {
String PARAM_GUI_ERROMSG = "errorMsg";
@@ -37,6 +36,9 @@ public interface IProtocolAuthenticationService {
String PARAM_GUI_EXTERNAL_ERRORCODE = "extErrorCode";
String PARAM_GUI_ERRORCODEPARAMS = "errorParams";
String PARAM_GUI_ERRORSTACKTRACE = "stacktrace";
+ String PARAM_GUI_TICKET = "supportTicket";
+ String PARAM_GUI_REDIRECT = "redirectLink";
+
/**
* Initialize an authentication process for this protocol request.
diff --git a/eaaf_core_utils/pom.xml b/eaaf_core_utils/pom.xml
index 4e3bbeee..e0cb88e3 100644
--- a/eaaf_core_utils/pom.xml
+++ b/eaaf_core_utils/pom.xml
@@ -121,8 +121,23 @@
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-tls</artifactId>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bctls-jdk15on</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.2.3</version>
+ <scope>test</scope>
</dependency>
-
</dependencies>
<build>
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/EaafSslContextBuilder.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/EaafSslContextBuilder.java
new file mode 100644
index 00000000..1cd739de
--- /dev/null
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/EaafSslContextBuilder.java
@@ -0,0 +1,433 @@
+package at.gv.egiz.eaaf.core.impl.http;
+
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509ExtendedKeyManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.http.ssl.PrivateKeyDetails;
+import org.apache.http.ssl.PrivateKeyStrategy;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.TrustStrategy;
+import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
+
+/**
+ * Fork of {@link SSLContextBuilder} that uses JSSE provider to get TrustManager.
+ *
+ * <p>This implementation fix an incompatibility between {@link BouncyCastleJsseProvider} and JAVA JDK >= v9</p>
+ *
+ * @author tlenz
+ *
+ */
+public class EaafSslContextBuilder {
+
+ static final String TLS = "TLS";
+
+ private String protocol;
+ private final Set<KeyManager> keyManagers;
+ private String keyManagerFactoryAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
+ private String keyStoreType = KeyStore.getDefaultType();
+ private final Set<TrustManager> trustManagers;
+ private String trustManagerFactoryAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ private SecureRandom secureRandom;
+ private Provider provider;
+
+ public static EaafSslContextBuilder create() {
+ return new EaafSslContextBuilder();
+ }
+
+ /**
+ * Get a new SSLContext builder object.
+ */
+ public EaafSslContextBuilder() {
+ super();
+ this.keyManagers = new LinkedHashSet<>();
+ this.trustManagers = new LinkedHashSet<>();
+ }
+
+ /**
+ * Sets the SSLContext protocol algorithm name.
+ *
+ * @param protocol the SSLContext protocol algorithm name of the requested
+ * protocol. See the SSLContext section in the <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext">Java
+ * Cryptography Architecture Standard Algorithm Name
+ * Documentation</a> for more information.
+ * @return this builder
+ * @see <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext">Java
+ * Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * @deprecated Use {@link #setProtocol(String)}.
+ */
+ @Deprecated
+ public EaafSslContextBuilder useProtocol(final String protocol) {
+ this.protocol = protocol;
+ return this;
+ }
+
+ /**
+ * Sets the SSLContext protocol algorithm name.
+ *
+ * @param protocol the SSLContext protocol algorithm name of the requested
+ * protocol. See the SSLContext section in the <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext">Java
+ * Cryptography Architecture Standard Algorithm Name
+ * Documentation</a> for more information.
+ * @return this builder
+ * @see <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext">Java
+ * Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * @since 4.4.7
+ */
+ public EaafSslContextBuilder setProtocol(final String protocol) {
+ this.protocol = protocol;
+ return this;
+ }
+
+ public EaafSslContextBuilder setSecureRandom(final SecureRandom secureRandom) {
+ this.secureRandom = secureRandom;
+ return this;
+ }
+
+ public EaafSslContextBuilder setProvider(final Provider provider) {
+ this.provider = provider;
+ return this;
+ }
+
+ public EaafSslContextBuilder setProvider(final String name) {
+ this.provider = Security.getProvider(name);
+ return this;
+ }
+
+ /**
+ * Sets the key store type.
+ *
+ * @param keyStoreType the SSLkey store type. See the KeyStore section in the
+ * <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore">Java
+ * Cryptography Architecture Standard Algorithm Name
+ * Documentation</a> for more information.
+ * @return this builder
+ * @see <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore">Java
+ * Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * @since 4.4.7
+ */
+ public EaafSslContextBuilder setKeyStoreType(final String keyStoreType) {
+ this.keyStoreType = keyStoreType;
+ return this;
+ }
+
+ /**
+ * Sets the key manager factory algorithm name.
+ *
+ * @param keyManagerFactoryAlgorithm the key manager factory algorithm name of
+ * the requested protocol. See the
+ * KeyManagerFactory section in the <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyManagerFactory">Java
+ * Cryptography Architecture Standard
+ * Algorithm Name Documentation</a> for more
+ * information.
+ * @return this builder
+ * @see <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyManagerFactory">Java
+ * Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * @since 4.4.7
+ */
+ public EaafSslContextBuilder setKeyManagerFactoryAlgorithm(final String keyManagerFactoryAlgorithm) {
+ this.keyManagerFactoryAlgorithm = keyManagerFactoryAlgorithm;
+ return this;
+ }
+
+ /**
+ * Sets the trust manager factory algorithm name.
+ *
+ * @param trustManagerFactoryAlgorithm the trust manager algorithm name of the
+ * requested protocol. See the
+ * TrustManagerFactory section in the
+ * <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#TrustManagerFactory">Java
+ * Cryptography Architecture Standard
+ * Algorithm Name Documentation</a> for more
+ * information.
+ * @return this builder
+ * @see <a href=
+ * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#TrustManagerFactory">Java
+ * Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * @since 4.4.7
+ */
+ public EaafSslContextBuilder setTrustManagerFactoryAlgorithm(final String trustManagerFactoryAlgorithm) {
+ this.trustManagerFactoryAlgorithm = trustManagerFactoryAlgorithm;
+ return this;
+ }
+
+ /**
+ * Load custom truststore.
+ *
+ * @param truststore {@link KeyStore} if trusted certificates
+ * @param trustStrategy Trust validation strategy
+ * @return {@link EaafSslContextBuilder}
+ * @throws NoSuchAlgorithmException In case of an invalid TrustManager algorithm
+ * @throws KeyStoreException In case of an invalid KeyStore
+ */
+ public EaafSslContextBuilder loadTrustMaterial(
+ final KeyStore truststore,
+ final TrustStrategy trustStrategy) throws NoSuchAlgorithmException, KeyStoreException {
+
+ final String alg = trustManagerFactoryAlgorithm == null
+ ? TrustManagerFactory.getDefaultAlgorithm()
+ : trustManagerFactoryAlgorithm;
+
+ final TrustManagerFactory tmfactory = provider != null
+ ? TrustManagerFactory.getInstance(alg, provider)
+ : TrustManagerFactory.getInstance(alg);
+ tmfactory.init(truststore);
+ final TrustManager[] tms = tmfactory.getTrustManagers();
+ if (tms != null) {
+ if (trustStrategy != null) {
+ for (int i = 0; i < tms.length; i++) {
+ final TrustManager tm = tms[i];
+ if (tm instanceof X509TrustManager) {
+ tms[i] = new TrustManagerDelegate((X509TrustManager) tm, trustStrategy);
+ }
+ }
+ }
+ Collections.addAll(this.trustManagers, tms);
+ }
+ return this;
+ }
+
+ public EaafSslContextBuilder loadTrustMaterial(
+ final TrustStrategy trustStrategy) throws NoSuchAlgorithmException, KeyStoreException {
+ return loadTrustMaterial(null, trustStrategy);
+ }
+
+
+ /**
+ * Load SSL client-authentication key-material into SSL context.
+ *
+ * @param keystore {@link KeyStore} for SSL client-authentication
+ * @param keyPassword Password for this keystore
+ * @param aliasStrategy Stategy to select keys by alias
+ * @return {@link EaafSslContextBuilder}
+ * @throws NoSuchAlgorithmException In case of an invalid KeyManagerFactory algorithm
+ * @throws KeyStoreException In case of an invalid KeyStore
+ * @throws UnrecoverableKeyException In case of a invalid Key in this KeyStore
+ */
+ public EaafSslContextBuilder loadKeyMaterial(
+ final KeyStore keystore,
+ final char[] keyPassword,
+ final PrivateKeyStrategy aliasStrategy)
+ throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
+ final KeyManagerFactory kmfactory = KeyManagerFactory
+ .getInstance(keyManagerFactoryAlgorithm == null ? KeyManagerFactory.getDefaultAlgorithm()
+ : keyManagerFactoryAlgorithm);
+ kmfactory.init(keystore, keyPassword);
+ final KeyManager[] kms = kmfactory.getKeyManagers();
+ if (kms != null) {
+ if (aliasStrategy != null) {
+ for (int i = 0; i < kms.length; i++) {
+ final KeyManager km = kms[i];
+ if (km instanceof X509ExtendedKeyManager) {
+ kms[i] = new KeyManagerDelegate((X509ExtendedKeyManager) km, aliasStrategy);
+ }
+ }
+ }
+ Collections.addAll(keyManagers, kms);
+ }
+ return this;
+ }
+
+ public EaafSslContextBuilder loadKeyMaterial(
+ final KeyStore keystore,
+ final char[] keyPassword) throws NoSuchAlgorithmException, KeyStoreException,
+ UnrecoverableKeyException {
+ return loadKeyMaterial(keystore, keyPassword, null);
+ }
+
+ protected void initSslContext(
+ final SSLContext sslContext,
+ final Collection<KeyManager> keyManagers,
+ final Collection<TrustManager> trustManagers,
+ final SecureRandom secureRandom) throws KeyManagementException {
+ sslContext.init(
+ !keyManagers.isEmpty() ? keyManagers.toArray(new KeyManager[keyManagers.size()]) : null,
+ !trustManagers.isEmpty() ? trustManagers.toArray(new TrustManager[trustManagers.size()]) : null,
+ secureRandom);
+ }
+
+ /**
+ * Build a {@link SSLContext} from this builder.
+ *
+ * @return new {@link SSLContext}
+ * @throws NoSuchAlgorithmException In case of an unknown SSL protocol
+ * @throws KeyManagementException In case of a key-access error
+ */
+ public SSLContext build() throws NoSuchAlgorithmException, KeyManagementException {
+ final SSLContext sslContext;
+ final String protocolStr = this.protocol != null ? this.protocol : TLS;
+ if (this.provider != null) {
+ sslContext = SSLContext.getInstance(protocolStr, this.provider);
+ } else {
+ sslContext = SSLContext.getInstance(protocolStr);
+ }
+ initSslContext(sslContext, keyManagers, trustManagers, secureRandom);
+ return sslContext;
+ }
+
+ static class TrustManagerDelegate implements X509TrustManager {
+
+ private final X509TrustManager trustManager;
+ private final TrustStrategy trustStrategy;
+
+ TrustManagerDelegate(final X509TrustManager trustManager, final TrustStrategy trustStrategy) {
+ super();
+ this.trustManager = trustManager;
+ this.trustStrategy = trustStrategy;
+ }
+
+ @Override
+ public void checkClientTrusted(
+ final X509Certificate[] chain, final String authType) throws CertificateException {
+ this.trustManager.checkClientTrusted(chain, authType);
+ }
+
+ @Override
+ public void checkServerTrusted(
+ final X509Certificate[] chain, final String authType) throws CertificateException {
+ if (!this.trustStrategy.isTrusted(chain, authType)) {
+ this.trustManager.checkServerTrusted(chain, authType);
+ }
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return this.trustManager.getAcceptedIssuers();
+ }
+
+ }
+
+ static class KeyManagerDelegate extends X509ExtendedKeyManager {
+
+ private final X509ExtendedKeyManager keyManager;
+ private final PrivateKeyStrategy aliasStrategy;
+
+ KeyManagerDelegate(final X509ExtendedKeyManager keyManager, final PrivateKeyStrategy aliasStrategy) {
+ super();
+ this.keyManager = keyManager;
+ this.aliasStrategy = aliasStrategy;
+ }
+
+ @Override
+ public String[] getClientAliases(
+ final String keyType, final Principal[] issuers) {
+ return this.keyManager.getClientAliases(keyType, issuers);
+ }
+
+ public Map<String, PrivateKeyDetails> getClientAliasMap(
+ final String[] keyTypes, final Principal[] issuers) {
+ final Map<String, PrivateKeyDetails> validAliases = new HashMap<>();
+ for (final String keyType : keyTypes) {
+ final String[] aliases = this.keyManager.getClientAliases(keyType, issuers);
+ if (aliases != null) {
+ for (final String alias : aliases) {
+ validAliases.put(alias,
+ new PrivateKeyDetails(keyType, this.keyManager.getCertificateChain(alias)));
+ }
+ }
+ }
+ return validAliases;
+ }
+
+ public Map<String, PrivateKeyDetails> getServerAliasMap(
+ final String keyType, final Principal[] issuers) {
+ final Map<String, PrivateKeyDetails> validAliases = new HashMap<>();
+ final String[] aliases = this.keyManager.getServerAliases(keyType, issuers);
+ if (aliases != null) {
+ for (final String alias : aliases) {
+ validAliases.put(alias,
+ new PrivateKeyDetails(keyType, this.keyManager.getCertificateChain(alias)));
+ }
+ }
+ return validAliases;
+ }
+
+ @Override
+ public String chooseClientAlias(
+ final String[] keyTypes, final Principal[] issuers, final Socket socket) {
+ final Map<String, PrivateKeyDetails> validAliases = getClientAliasMap(keyTypes, issuers);
+ return this.aliasStrategy.chooseAlias(validAliases, socket);
+ }
+
+ @Override
+ public String[] getServerAliases(
+ final String keyType, final Principal[] issuers) {
+ return this.keyManager.getServerAliases(keyType, issuers);
+ }
+
+ @Override
+ public String chooseServerAlias(
+ final String keyType, final Principal[] issuers, final Socket socket) {
+ final Map<String, PrivateKeyDetails> validAliases = getServerAliasMap(keyType, issuers);
+ return this.aliasStrategy.chooseAlias(validAliases, socket);
+ }
+
+ @Override
+ public X509Certificate[] getCertificateChain(final String alias) {
+ return this.keyManager.getCertificateChain(alias);
+ }
+
+ @Override
+ public PrivateKey getPrivateKey(final String alias) {
+ return this.keyManager.getPrivateKey(alias);
+ }
+
+ @Override
+ public String chooseEngineClientAlias(
+ final String[] keyTypes, final Principal[] issuers, final SSLEngine sslEngine) {
+ final Map<String, PrivateKeyDetails> validAliases = getClientAliasMap(keyTypes, issuers);
+ return this.aliasStrategy.chooseAlias(validAliases, null);
+ }
+
+ @Override
+ public String chooseEngineServerAlias(
+ final String keyType, final Principal[] issuers, final SSLEngine sslEngine) {
+ final Map<String, PrivateKeyDetails> validAliases = getServerAliasMap(keyType, issuers);
+ return this.aliasStrategy.chooseAlias(validAliases, null);
+ }
+
+ }
+
+ @Override
+ public String toString() {
+ return "[provider=" + provider + ", protocol=" + protocol + ", keyStoreType=" + keyStoreType
+ + ", keyManagerFactoryAlgorithm=" + keyManagerFactoryAlgorithm + ", keyManagers=" + keyManagers
+ + ", trustManagerFactoryAlgorithm=" + trustManagerFactoryAlgorithm + ", trustManagers="
+ + trustManagers
+ + ", secureRandom=" + secureRandom + "]";
+ }
+}
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpUtils.java
index 365e969d..3058c9b5 100644
--- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpUtils.java
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpUtils.java
@@ -40,8 +40,6 @@ import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.entity.ContentType;
-import org.apache.http.ssl.SSLContextBuilder;
-import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
@@ -56,7 +54,6 @@ import lombok.extern.slf4j.Slf4j;
public class HttpUtils {
private static final String ERROR_03 = "internal.httpclient.03";
-
/**
* Simple Http response-handler that only give http status-code as result.
@@ -174,7 +171,7 @@ public class HttpUtils {
* @param url URL
* @param paramname Name of the parameter.
* @param paramvalue Value of the parameter.
- * @return
+ * @return Url with parameter
*/
public static String addUrlParameter(final String url, final String paramname,
final String paramvalue) {
@@ -210,7 +207,7 @@ public class HttpUtils {
boolean trustAllServerCertificates, @Nonnull String friendlyName)
throws EaafConfigurationException, EaafFactoryException {
try {
- SSLContextBuilder sslContextBuilder = SSLContexts.custom();
+ EaafSslContextBuilder sslContextBuilder = EaafSslContextBuilder.create();
injectKeyStore(sslContextBuilder, keyStore, keyAlias, keyPasswordString, friendlyName);
@@ -251,7 +248,7 @@ public class HttpUtils {
@Nonnull String friendlyName)
throws EaafConfigurationException, EaafFactoryException {
try {
- SSLContextBuilder sslContextBuilder = SSLContexts.custom();
+ EaafSslContextBuilder sslContextBuilder = EaafSslContextBuilder.create();
injectKeyStore(sslContextBuilder, keyStore, keyAlias, keyPasswordString, friendlyName);
@@ -266,7 +263,7 @@ public class HttpUtils {
}
}
- private static void injectTrustStore(SSLContextBuilder sslContextBuilder,
+ private static void injectTrustStore(EaafSslContextBuilder sslContextBuilder,
Pair<KeyStore, Provider> trustStore, boolean trustAllServerCertificates, String friendlyName)
throws NoSuchAlgorithmException, KeyStoreException {
@@ -276,7 +273,7 @@ public class HttpUtils {
trustStrategy = new TrustAllStrategy();
}
-
+
KeyStore trustStoreImpl = null;
if (trustStore != null) {
log.info("Http-client: {} uses custom TrustStore.", friendlyName);
@@ -288,16 +285,18 @@ public class HttpUtils {
}
- private static void injectKeyStore(SSLContextBuilder sslContextBuilder, Pair<KeyStore, Provider> keyStore,
+ private static void injectKeyStore(EaafSslContextBuilder sslContextBuilder, Pair<KeyStore, Provider> keyStore,
String keyAlias, String keyPasswordString, String friendlyName)
throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException {
+
+ Provider provider;
if (keyStore.getSecond() != null) {
- Provider provider = new BouncyCastleJsseProvider(keyStore.getSecond());
+ provider = new BouncyCastleJsseProvider(keyStore.getSecond());
log.debug("KeyStore: {} provide special security-provider. Inject: {} into SSLContext",
friendlyName, provider.getName());
sslContextBuilder.setProvider(provider);
- }
+ }
log.trace("Open SSL Client-Auth keystore with password: {}", keyPasswordString);
final char[] keyPassword = keyPasswordString == null ? StringUtils.EMPTY.toCharArray()
@@ -313,5 +312,4 @@ public class HttpUtils {
}
}
-
}
diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryProdHostTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryProdHostTest.java
new file mode 100644
index 00000000..55c17ee8
--- /dev/null
+++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryProdHostTest.java
@@ -0,0 +1,98 @@
+package at.gv.egiz.eaaf.core.test.http;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Base64;
+
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.MethodMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.http.HttpClientConfiguration;
+import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("/spring/test_eaaf_pvp_not_lazy.beans.xml")
+@DirtiesContext
+public class HttpClientFactoryProdHostTest {
+
+ @Autowired private IHttpClientFactory httpClientFactory;
+ @Autowired private EaafKeyStoreFactory keyStoreFactory;
+
+ /**
+ * Initialize full class.
+ */
+ @BeforeClass
+ public static void classInitializer() {
+ final Logger logger = (Logger) LoggerFactory.getLogger("org.bouncycastle.jsse");
+ logger.setLevel(Level.TRACE);
+
+ }
+
+ /**
+ * JUnit test set-up.
+ *
+ */
+ @Before
+ public void setup() {
+
+ }
+
+ @Test
+ @DirtiesContext(methodMode = MethodMode.BEFORE_METHOD)
+ public void getCustomClientX509AuthWithHsmFacadeTrustStore() throws EaafException, ClientProtocolException,
+ IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException,
+ CertificateEncodingException {
+ System.setProperty("javax.net.debug", "ssl:handshake");
+
+ final HttpClientConfiguration clientConfig = new HttpClientConfiguration("jUnit-client");
+ clientConfig.setAuthMode("ssl");
+ //clientConfig.buildKeyStoreConfig("hsmfacade", null, null, "eid-junit");
+ //clientConfig.setSslKeyAlias("rsa-key-1");
+ clientConfig.buildKeyStoreConfig("hsmfacade", null, null, "authhandler");
+ clientConfig.setSslKeyAlias("authhandler-sign");
+ clientConfig.setDisableTlsHostCertificateValidation(false);
+
+ final CloseableHttpClient client = httpClientFactory.getHttpClient(clientConfig);
+ Assert.assertNotNull("httpClient", client);
+
+ final Pair<KeyStore, Provider> sslClientKeyStore =
+ keyStoreFactory.buildNewKeyStore(clientConfig.getKeyStoreConfig());
+ final X509Certificate clientRootCert = (X509Certificate) sslClientKeyStore.getFirst()
+ .getCertificateChain(clientConfig.getSslKeyAlias())[1];
+ final X509Certificate clientEeCert = (X509Certificate) sslClientKeyStore.getFirst()
+ .getCertificateChain(clientConfig.getSslKeyAlias())[0];
+ Base64.getEncoder().encodeToString(clientEeCert.getEncoded());
+
+ //perform test request
+ final HttpUriRequest httpGet2 = new HttpGet("https://apps.egiz.gv.at//sslclientcertdemo/");
+ final CloseableHttpResponse httpResp2 = client.execute(httpGet2);
+ Assert.assertEquals("http statusCode", 200, httpResp2.getStatusLine().getStatusCode());
+
+ }
+
+}
diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryTest.java
index baedadc8..c71d8352 100644
--- a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryTest.java
+++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/http/HttpClientFactoryTest.java
@@ -5,9 +5,14 @@ import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.SocketTimeoutException;
+import java.security.Key;
+import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
import java.security.Provider;
+import java.security.UnrecoverableKeyException;
import java.security.cert.X509Certificate;
import org.apache.commons.lang3.RandomStringUtils;
@@ -20,10 +25,13 @@ import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.MethodMode;
@@ -32,12 +40,16 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import at.gv.egiz.eaaf.core.exceptions.EaafException;
import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType;
import at.gv.egiz.eaaf.core.impl.data.Pair;
import at.gv.egiz.eaaf.core.impl.data.Triple;
import at.gv.egiz.eaaf.core.impl.http.HttpClientConfiguration;
import at.gv.egiz.eaaf.core.impl.http.HttpUtils;
import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory;
import at.gv.egiz.eaaf.core.impl.utils.StreamUtils;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
import okhttp3.HttpUrl;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
@@ -58,6 +70,27 @@ public class HttpClientFactoryTest {
private HttpUrl mockServerUrl;
/**
+ * Initialize full class.
+ */
+ @BeforeClass
+ public static void classInitializer() {
+ final Logger logger = (Logger) LoggerFactory.getLogger("org.bouncycastle.jsse");
+ logger.setLevel(Level.TRACE);
+
+ }
+
+ /**
+ * Reset test environment.
+ */
+ @AfterClass
+ public static void classReset() {
+ System.clearProperty("javax.net.ssl.trustStoreType");
+ System.clearProperty("javax.net.ssl.trustStore");
+ System.clearProperty("javax.net.ssl.trustStorePassword");
+
+ }
+
+ /**
* JUnit test set-up.
*
*/
@@ -595,4 +628,67 @@ public class HttpClientFactoryTest {
}
+ @Test
+ @DirtiesContext(methodMode = MethodMode.BEFORE_METHOD)
+ public void getCustomClientX509AuthWithHsmFacadeTrustStore() throws EaafException, ClientProtocolException,
+ IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException {
+
+ final String current = new java.io.File(".").getCanonicalPath();
+ System.setProperty("javax.net.ssl.trustStoreType", "jks");
+ System.setProperty("javax.net.ssl.trustStore",
+ current + "/src/test/resources/data/ssL_truststore.jks");
+ System.setProperty("javax.net.ssl.trustStorePassword",
+ "password");
+
+ final KeyStoreConfiguration sslServerCertConfig = new KeyStoreConfiguration();
+ sslServerCertConfig.setKeyStoreType(KeyStoreType.JKS);
+ sslServerCertConfig.setFriendlyName("SSL host cert");
+ sslServerCertConfig.setSoftKeyStoreFilePath("src/test/resources/data/ssl_host.jks");
+ sslServerCertConfig.setSoftKeyStorePassword("password");
+
+ Pair<KeyStore, Provider> sslServerHostKeyStore =
+ keyStoreFactory.buildNewKeyStore(sslServerCertConfig);
+
+
+ final HttpClientConfiguration clientConfig = new HttpClientConfiguration("jUnit-client");
+ clientConfig.setAuthMode("ssl");
+ clientConfig.buildKeyStoreConfig("hsmfacade", null, null, "authhandler");
+ clientConfig.setSslKeyAlias("authhandler-sign");
+ clientConfig.setDisableTlsHostCertificateValidation(false);
+
+ final CloseableHttpClient client = httpClientFactory.getHttpClient(clientConfig);
+ Assert.assertNotNull("httpClient", client);
+
+ //set-up mock-up web-server with SSL client authentication
+ final Pair<KeyStore, Provider> sslClientKeyStore =
+ keyStoreFactory.buildNewKeyStore(clientConfig.getKeyStoreConfig());
+ final X509Certificate clientRootCert = (X509Certificate) sslClientKeyStore.getFirst()
+ .getCertificateChain(clientConfig.getSslKeyAlias())[1];
+ final X509Certificate clientEeCert = (X509Certificate) sslClientKeyStore.getFirst()
+ .getCertificateChain(clientConfig.getSslKeyAlias())[0];
+
+ Key sslKey = sslServerHostKeyStore.getFirst().getKey("ssl", "password".toCharArray());
+ X509Certificate sslCert = (X509Certificate) sslServerHostKeyStore.getFirst().getCertificate("ssl");
+ KeyPair keyPair = new KeyPair(sslCert.getPublicKey(), (PrivateKey) sslKey);
+ HeldCertificate localhostCertificate = new HeldCertificate(keyPair, sslCert);
+ final HandshakeCertificates serverCertificates = new HandshakeCertificates.Builder()
+ .addTrustedCertificate(clientEeCert)
+ .addTrustedCertificate(clientRootCert)
+ .heldCertificate(localhostCertificate)
+ .build();
+ mockWebServer = new MockWebServer();
+
+ mockWebServer.useHttps(serverCertificates.sslSocketFactory(), false);
+ mockWebServer.requireClientAuth();
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody("Successful auth!"));
+ mockServerUrl = mockWebServer.url("/sp/junit");
+
+ //perform test request
+ final HttpUriRequest httpGet2 = new HttpGet(mockServerUrl.url().toString());
+ final CloseableHttpResponse httpResp2 = client.execute(httpGet2);
+ Assert.assertEquals("http statusCode", 200, httpResp2.getStatusLine().getStatusCode());
+
+ }
+
}
diff --git a/eaaf_core_utils/src/test/resources/data/hsm_ee-RSA_rootcert.crt b/eaaf_core_utils/src/test/resources/data/hsm_ee-RSA_rootcert.crt
new file mode 100644
index 00000000..aa83c8d9
--- /dev/null
+++ b/eaaf_core_utils/src/test/resources/data/hsm_ee-RSA_rootcert.crt
@@ -0,0 +1,3 @@
+-----BEGIN CERTIFICATE-----
+MIICDTCCAbOgAwIBAgIIVLxIFI8kRpkwCgYIKoZIzj0EAwIwEjEQMA4GA1UEAwwHRUMtUm9vdDAeFw0yMDA2MTgwNzM2MTBaFw0yNTA2MTgwNzM2MTBaMDwxGzAZBgNVBAMMEmludC1yc2Eta2V5LTEtMDAwMTERMA8GA1UECgwIc29mdHdhcmUxCjAIBgNVBAUTATEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDrM1ocQqtch95Dm21JHi0V35nlWZibsjLqR+g8ERdD1qFgun/X0I/Rbft+KxB8QsDX7UmIjXGdavNcEjY/XcbiJxUcpv7vn/2+x3JxZO6Iye/ut001okICt3OGIqP93ZEnIaTTNhDsK7OnvD/eUjlmuHiTaFq1dZLKYDQlz9jl/9F4axfrz1V7oo60iqFIW+7tlUeh8VGDUPjQpHghzjHXTJv/OIAt752K31Tn8KR3kvkn6WTPo8eOWVaPQ480Dik0e2afTPPJNZJ7BW111IwqBAOKp586yVsQ4XVEF8H64Cq+s+b4/HBboo9TDJKTJvo2yQmcTsahbH+Rlm20ifUTAgMBAAEwCgYIKoZIzj0EAwIDSAAwRQIhANKN/N2Atb5fbeHSB2Myv/JcNf9JonxFe92AOu4f62NNAiBjOEeg4OyJZKPiDl6aqYVtz1Qroo6xzUC9UVA4qNe4LA==
+-----END CERTIFICATE-----
diff --git a/eaaf_core_utils/src/test/resources/data/hsm_ee_eecert.crt b/eaaf_core_utils/src/test/resources/data/hsm_ee_eecert.crt
new file mode 100644
index 00000000..b4c47c78
--- /dev/null
+++ b/eaaf_core_utils/src/test/resources/data/hsm_ee_eecert.crt
@@ -0,0 +1,3 @@
+-----BEGIN CERTIFICATE-----
+MIIDEzCCArqgAwIBAgIIMrAOP6EqywMwCgYIKoZIzj0EAwIwEjEQMA4GA1UEAwwHRUMtUm9vdDAeFw0yMDA2MTgwNzM2MDlaFw0yNTA2MTgwNzM2MDlaMEMxIjAgBgNVBAMMGWludC1hdXRoaGFuZGxlci1zaWduLTAwMDExETAPBgNVBAoMCHNvZnR3YXJlMQowCAYDVQQFEwExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5j2vR8ZV88fOJzFHmLuPizHXk+aiE0fX8Bu63FqCNa2Vy343u2k+4HVQBWpAtyRej8nL7JQuhFa11YRtVF+Vos9cyUDk482sUlYA2LdAFIuHJP6iTRrrHYdiTskc3FQUm9m9KorVFwnfzqJ40wjn9hD0xKCE0odk9IHA5aLTul0mSMcHQ+MMu2cbelK2TWTEC0wcGum2NrTWukhf0E4/e4SuqMgEUPdHSEaNZLGKZU0kyVtXKK0HCtWF8OKGay4V504dk3qnmRHHO8ik3oyPk2yLipQAPL0bUGMZ7tlRLo5VxJvkZSsJfAzvYn1JzcQIt6bXszQGU/JS6dw7Jq99Ckzox/vk8p1YUPd4tCuUJPXzhFhI7CedHKGItwk7mQf5llgeVJy40sVrFwHLDPufY5mlm9C+gVBs71+ibT/sJ96gCueWqduzDX8fHzeaNVj2NFEx2pT46D5cbRWZBow3+Rx+hpge6SDMzaebpbkgLPX+35D952bMLjm+9T0DulGk1tLL2k4YK+1WWUprlo+rm65OA5FxnO5YxNmGk2Uizu3tSoZMxmXwEWoFfYaMsTt5Not3+CLPjfs6pE4ML9ifAOxW+pPsmanDiNaMiL0/aSddvvkv3lSMRiU9nYh3DuOu6sGIMaPdyYF0V/9Fua2SDZV3QKIbzPbJfEsXFKtjtzUCAwEAATAKBggqhkjOPQQDAgNHADBEAiBHsK819KfxVn91KAmjRjb7zx8TLLBApyaZHXi5HVrYUwIgQbF6u6bXziAWdijlJC0IOWdBuTLWmTvFqBH7uX1HL9c=
+-----END CERTIFICATE-----
diff --git a/eaaf_core_utils/src/test/resources/data/hsm_ee_rootcert.crt b/eaaf_core_utils/src/test/resources/data/hsm_ee_rootcert.crt
new file mode 100644
index 00000000..fa7b132f
--- /dev/null
+++ b/eaaf_core_utils/src/test/resources/data/hsm_ee_rootcert.crt
@@ -0,0 +1,3 @@
+-----BEGIN CERTIFICATE-----
+MIIBPDCB46ADAgECAghZ0/gtbA6FrjAKBggqhkjOPQQDAjASMRAwDgYDVQQDDAdFQy1Sb290MB4XDTIwMDYxODA3MzU1M1oXDTMwMDYxODA3MzU1M1owEjEQMA4GA1UEAwwHRUMtUm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIjgL+6qiE9oj2yWCkVm6s7AaYkbDhTptYXTW92MhASiTqxL6g8tr28MlRA2P8HPrNSK9payeMe5QW9Kxn+EMPejIzAhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgWgMAoGCCqGSM49BAMCA0gAMEUCIDq2f4xjYD8pzr+mdzuT8wzePRnj/EatjmimGnvNt3FjAiEArezudh6G+wE+ds6S0dnFxG0o/BrbR0fiRNTQwiZA9ec=
+-----END CERTIFICATE-----
diff --git a/eaaf_core_utils/src/test/resources/data/server_host.crt b/eaaf_core_utils/src/test/resources/data/server_host.crt
new file mode 100644
index 00000000..21d3a1e4
--- /dev/null
+++ b/eaaf_core_utils/src/test/resources/data/server_host.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC2TCCAcECBGB5WpEwDQYJKoZIhvcNAQELBQAwMTELMAkGA1UEBhMCQVQxDjAM
+BgNVBAsMBWpVbml0MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMjEwNDE2MDkzNjE3
+WhcNMjQwMTEwMDkzNjE3WjAxMQswCQYDVQQGEwJBVDEOMAwGA1UECwwFalVuaXQx
+EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAJVYLzPzq7oBGS5Wer0++rHbp+DWI7srAV1lGHdq8ST6APh/7fEVWpdZDpMY
+bOXl6uIiVmMsx/jUhQwOu4rFXThiQlwyQOv57SO7WHqNPqbRs/EUVnzW35aXU/DB
+CmkqKyjK/+vuq7tIahlpqrppCzBVC9/Z15U+RMTdnATrohALNJovydH3VSkdkKX0
+5BDx779/8malTgyWTUgl+p3F/91iIIl4ZvIngo2ZYQCFm1nV6jmpErGFkG6YVrO7
+oe3OlGKFiXtqCmq+NSFeXsv/SaXWNUw82pYKuK/5EFSLX49HLBBDI14eOCuVLnGA
+H/kG3tGteYMBNzSMmC/kcKgRDnUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAJn2
+a/VbtXGmHe9wmtu8K3noyECfG5fbu9URUjXhCBlXGcdjfz1gzrOHcmaBndk0a566
+R2W0fLvjLpjWChrj7r34EpNYGPMLV2gp3ZkiSGl9kv8mf9iChK6+ga3SlyHJuXXu
+gw6eOIAxBrE/vLw+pZtCEV9yPrIydkt19jjejf1wjs5y2G7m5r5pBIh6Wlmmc4f2
+3M6l6Dge78WVdUaU5AeAHjgGgXwULxmLGxi6yiS5HsSeb79oGz9psHbq1EAvwOVY
+sLepTbDQvX/VAAG7HOJXhdGM0fRIkM7HFA5+6joTHvAKhuMlFIJ8Y4QIG2QaIBAh
+eBBh91x/aB2xOKs+Kg==
+-----END CERTIFICATE-----
diff --git a/eaaf_core_utils/src/test/resources/data/ssL_truststore.jks b/eaaf_core_utils/src/test/resources/data/ssL_truststore.jks
new file mode 100644
index 00000000..4d7bc2f3
--- /dev/null
+++ b/eaaf_core_utils/src/test/resources/data/ssL_truststore.jks
Binary files differ
diff --git a/eaaf_core_utils/src/test/resources/data/ssl_host.jks b/eaaf_core_utils/src/test/resources/data/ssl_host.jks
new file mode 100644
index 00000000..4ca07595
--- /dev/null
+++ b/eaaf_core_utils/src/test/resources/data/ssl_host.jks
Binary files differ
diff --git a/pom.xml b/pom.xml
index 515b72d3..6d62b94c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,8 +52,8 @@
<org.opensaml.version>3.4.5</org.opensaml.version>
<org.apache.santuario.xmlsec.version>2.2.0</org.apache.santuario.xmlsec.version>
<org.cryptacular.version>1.2.4</org.cryptacular.version>
- <org.bouncycastle.bcprov-jdk15to18.version>1.67</org.bouncycastle.bcprov-jdk15to18.version>
- <org.bouncycastle.bctls-jdk15to18.version>1.67</org.bouncycastle.bctls-jdk15to18.version>
+ <org.bouncycastle.bcprov-jdk15to18.version>1.68</org.bouncycastle.bcprov-jdk15to18.version>
+ <org.bouncycastle.bctls-jdk15to18.version>1.68</org.bouncycastle.bctls-jdk15to18.version>
<org.slf4j.version>1.7.30</org.slf4j.version>
<ch.qos.logback-access.version>1.2.3</ch.qos.logback-access.version>
@@ -89,7 +89,7 @@
<org.powermock.version>2.0.9</org.powermock.version>
<!-- Code helper plug-ins -->
- <org.projectlombok.lombok.version>1.18.12</org.projectlombok.lombok.version>
+ <org.projectlombok.lombok.version>1.18.16</org.projectlombok.lombok.version>
<!-- Code quality checks -->
<jacoco-maven-plugin.version>0.8.6</jacoco-maven-plugin.version>