aboutsummaryrefslogtreecommitdiff
path: root/id.server/src/at/gv/egovernment/moa
diff options
context:
space:
mode:
authorrudolf <rudolf@d688527b-c9ab-4aba-bd8d-4036d912da1d>2003-10-24 08:34:56 +0000
committerrudolf <rudolf@d688527b-c9ab-4aba-bd8d-4036d912da1d>2003-10-24 08:34:56 +0000
commitdd45e938564249a5e6897bd92dd29808d8990868 (patch)
tree372d8a4b128cff09262ad09d6a4cf5765d672d61 /id.server/src/at/gv/egovernment/moa
parent59f78a67d7357fd31de68fc2b623f95b3d654ebc (diff)
downloadmoa-id-spss-dd45e938564249a5e6897bd92dd29808d8990868.tar.gz
moa-id-spss-dd45e938564249a5e6897bd92dd29808d8990868.tar.bz2
moa-id-spss-dd45e938564249a5e6897bd92dd29808d8990868.zip
MOA-ID version 1.1 (initial)
git-svn-id: https://joinup.ec.europa.eu/svn/moa-idspss/trunk@19 d688527b-c9ab-4aba-bd8d-4036d912da1d
Diffstat (limited to 'id.server/src/at/gv/egovernment/moa')
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/AuthenticationException.java31
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/BuildException.java34
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/MOAIDException.java159
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/ParseException.java34
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/ServiceException.java34
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java648
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java52
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java53
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java118
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/WrongParametersException.java21
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/AuthenticationBlockAssertionBuilder.java56
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataAssertionBuilder.java114
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/Builder.java30
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/CertInfoVerifyXMLSignatureRequestBuilder.java51
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java58
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/DataURLBuilder.java55
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/GetIdentityLinkFormBuilder.java137
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/InfoboxReadRequestBuilder.java39
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/PersonDataBuilder.java58
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilder.java60
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/SAMLResponseBuilder.java100
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/SelectBKUFormBuilder.java63
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/VPKBuilder.java52
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/builder/VerifyXMLSignatureRequestBuilder.java203
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java220
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/data/CreateXMLSignatureResponse.java71
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/data/IdentityLink.java189
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/data/SAMLAttribute.java78
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/data/VerifyXMLSignatureResponse.java177
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java91
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/parser/CreateXMLSignatureResponseParser.java140
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/parser/ECDSAKeyValueConverter.java350
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/parser/ErrorResponseParser.java89
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java266
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/parser/InfoboxReadResponseParser.java110
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParser.java58
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java159
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java117
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/servlet/ConfigurationServlet.java74
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/servlet/GetAuthenticationDataService.java135
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/servlet/SelectBKUServlet.java95
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/servlet/StartAuthenticationServlet.java102
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java110
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java97
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java106
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/validator/IdentityLinkValidator.java156
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/validator/ValidateException.java35
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/validator/VerifyXMLSignatureResponseValidator.java124
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/config/ConfigurationBuilder.java678
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/config/ConfigurationException.java31
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/config/ConfigurationProvider.java105
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/config/ConnectionParameter.java106
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java341
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java93
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/config/proxy/OAConfiguration.java145
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/config/proxy/OAProxyParameter.java160
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/config/proxy/ProxyConfigurationProvider.java170
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/data/AuthenticationData.java314
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/data/Cookie.java119
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/data/CookieManager.java114
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/data/IssuerAndSerial.java111
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/data/SAMLStatus.java59
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/iaik/config/CertStoreConfigurationImpl.java91
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/iaik/config/LoggerConfigImpl.java51
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/iaik/config/PKIConfigurationImpl.java65
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/iaik/config/RevocationConfigurationImpl.java35
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/iaik/config/ValidationConfigurationImpl.java51
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/iaik/pki/PKIProfileImpl.java159
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/iaik/pki/jsse/MOAIDTrustManager.java119
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/iaik/servertools/observer/ObservableImpl.java46
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/ConnectionBuilder.java54
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/ConnectionBuilderFactory.java68
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/DefaultConnectionBuilder.java119
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/DefaultLoginParameterResolver.java118
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/LoginParameterResolver.java72
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/LoginParameterResolverFactory.java68
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/MOAIDProxyInitializer.java91
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/WebmailLoginParameterResolver.classbin0 -> 3613 bytes
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/builder/SAMLRequestBuilder.java55
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/invoke/GetAuthenticationDataInvoker.java143
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/parser/AuthenticationDataAssertionParser.java145
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/parser/SAMLResponseParser.java100
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ConfigurationServlet.java73
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ProxyException.java35
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ProxyServlet.java531
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/util/AxisSecureSocketFactory.java213
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/util/MOAIDMessageProvider.java58
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/util/Random.java22
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/util/SSLUtils.java156
89 files changed, 10693 insertions, 0 deletions
diff --git a/id.server/src/at/gv/egovernment/moa/id/AuthenticationException.java b/id.server/src/at/gv/egovernment/moa/id/AuthenticationException.java
new file mode 100644
index 000000000..96a5e0673
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/AuthenticationException.java
@@ -0,0 +1,31 @@
+package at.gv.egovernment.moa.id;
+
+
+/**
+ * Exception thrown during handling of AuthenticationSession
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class AuthenticationException extends MOAIDException {
+
+ /**
+ * Constructor for AuthenticationException.
+ * @param messageId
+ */
+ public AuthenticationException(String messageId, Object[] parameters) {
+ super(messageId, parameters, null);
+ }
+ /**
+ * Constructor for AuthenticationException.
+ * @param messageId
+ * @param parameters
+ * @param wrapped
+ */
+ public AuthenticationException(
+ String messageId,
+ Object[] parameters,
+ Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/BuildException.java b/id.server/src/at/gv/egovernment/moa/id/BuildException.java
new file mode 100644
index 000000000..785dce7a3
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/BuildException.java
@@ -0,0 +1,34 @@
+package at.gv.egovernment.moa.id;
+
+
+/**
+ * Exception thrown while building an XML or HTML structure.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class BuildException extends MOAIDException {
+
+ /**
+ * Constructor for BuildException.
+ * @param messageId
+ * @param parameters
+ */
+ public BuildException(String messageId, Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+ /**
+ * Constructor for BuildException.
+ * @param messageId
+ * @param parameters
+ * @param wrapped
+ */
+ public BuildException(
+ String messageId,
+ Object[] parameters,
+ Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/MOAIDException.java b/id.server/src/at/gv/egovernment/moa/id/MOAIDException.java
new file mode 100644
index 000000000..bce2c4778
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/MOAIDException.java
@@ -0,0 +1,159 @@
+package at.gv.egovernment.moa.id;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.util.Constants;
+
+/**
+ * Base class of technical MOA exceptions.
+ *
+ * Technical exceptions are exceptions that originate from system failure (e.g.,
+ * a database connection fails, a component is not available, etc.)
+ *
+ * @author Patrick Peck, Ivancsics Paul
+ * @version $Id$
+ */
+public class MOAIDException extends Exception {
+ /** message ID */
+ private String messageId;
+ /** wrapped exception */
+ private Throwable wrapped;
+
+ /**
+ * Create a new <code>MOAIDException</code>.
+ *
+ * @param messageId The identifier of the message associated with this
+ * exception.
+ * @param parameters Additional message parameters.
+ */
+ public MOAIDException(String messageId, Object[] parameters) {
+ super(MOAIDMessageProvider.getInstance().getMessage(messageId, parameters));
+ this.messageId = messageId;
+ }
+
+ /**
+ * Create a new <code>MOAIDException</code>.
+ *
+ * @param messageId The identifier of the message associated with this
+ * <code>MOAIDException</code>.
+ * @param parameters Additional message parameters.
+ * @param wrapped The exception wrapped by this
+ * <code>MOAIDException</code>.
+ */
+ public MOAIDException(
+ String messageId,
+ Object[] parameters,
+ Throwable wrapped) {
+
+ super(MOAIDMessageProvider.getInstance().getMessage(messageId, parameters));
+ this.messageId = messageId;
+ this.wrapped = wrapped;
+ }
+
+ /**
+ * Print a stack trace of this exception to <code>System.err</code>.
+ *
+ * @see java.lang.Throwable#printStackTrace()
+ */
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Print a stack trace of this exception, including the wrapped exception.
+ *
+ * @param s The stream to write the stack trace to.
+ * @see java.lang.Throwable#printStackTrace(java.io.PrintStream)
+ */
+ public void printStackTrace(PrintStream s) {
+ if (getWrapped() == null)
+ super.printStackTrace(s);
+ else {
+ s.print("Root exception: ");
+ getWrapped().printStackTrace(s);
+ }
+ }
+
+ /**
+ * Print a stack trace of this exception, including the wrapped exception.
+ *
+ * @param s The stream to write the stacktrace to.
+ * @see java.lang.Throwable#printStackTrace(java.io.PrintWriter)
+ */
+ public void printStackTrace(PrintWriter s) {
+ if (getWrapped() == null)
+ super.printStackTrace(s);
+ else {
+ s.print("Root exception: ");
+ getWrapped().printStackTrace(s);
+ }
+ }
+
+ /**
+ * @return message ID
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * @return wrapped exception
+ */
+ public Throwable getWrapped() {
+ return wrapped;
+ }
+
+ /**
+ * Convert this <code>MOAIDException</code> to an <code>ErrorResponse</code>
+ * element from the MOA namespace.
+ *
+ * @return An <code>ErrorResponse</code> element, containing the subelements
+ * <code>ErrorCode</code> and <code>Info</code> required by the MOA schema.
+ */
+ public Element toErrorResponse() {
+ DocumentBuilder builder;
+ DOMImplementation impl;
+ Document doc;
+ Element errorResponse;
+ Element errorCode;
+ Element info;
+
+ // create a new document
+ try {
+ builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ impl = builder.getDOMImplementation();
+ } catch (ParserConfigurationException e) {
+ return null;
+ }
+
+ // build the ErrorResponse element
+ doc = impl.createDocument(Constants.MOA_NS_URI, "ErrorResponse", null);
+ errorResponse = doc.getDocumentElement();
+
+ // add MOA namespace declaration
+ errorResponse.setAttributeNS(
+ Constants.XMLNS_NS_URI,
+ "xmlns",
+ Constants.MOA_NS_URI);
+
+ // build the child elements
+ errorCode = doc.createElementNS(Constants.MOA_NS_URI, "ErrorCode");
+ errorCode.appendChild(doc.createTextNode(messageId));
+ info = doc.createElementNS(Constants.MOA_NS_URI, "Info");
+ info.appendChild(doc.createTextNode(toString()));
+ errorResponse.appendChild(errorCode);
+ errorResponse.appendChild(info);
+ return errorResponse;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/ParseException.java b/id.server/src/at/gv/egovernment/moa/id/ParseException.java
new file mode 100644
index 000000000..a5e0088d9
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/ParseException.java
@@ -0,0 +1,34 @@
+package at.gv.egovernment.moa.id;
+
+
+/**
+ * Exception thrown while parsing an XML structure.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ParseException extends MOAIDException {
+
+ /**
+ * Constructor for ParseException.
+ * @param messageId
+ * @param parameters
+ */
+ public ParseException(String messageId, Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+ /**
+ * Constructor for ParseException.
+ * @param messageId
+ * @param parameters
+ * @param wrapped
+ */
+ public ParseException(
+ String messageId,
+ Object[] parameters,
+ Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/ServiceException.java b/id.server/src/at/gv/egovernment/moa/id/ServiceException.java
new file mode 100644
index 000000000..9e6ab2361
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/ServiceException.java
@@ -0,0 +1,34 @@
+package at.gv.egovernment.moa.id;
+
+
+/**
+ * Exception thrown while calling the MOA-SPSS web service.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ServiceException extends MOAIDException {
+
+ /**
+ * Constructor for ServiceException.
+ * @param messageId
+ * @param parameters
+ */
+ public ServiceException(String messageId, Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+ /**
+ * Constructor for ServiceException.
+ * @param messageId
+ * @param parameters
+ * @param wrapped
+ */
+ public ServiceException(
+ String messageId,
+ Object[] parameters,
+ Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java b/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java
new file mode 100644
index 000000000..e9d9c7175
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java
@@ -0,0 +1,648 @@
+package at.gv.egovernment.moa.id.auth;
+
+import iaik.pki.PKIException;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.AuthenticationException;
+import at.gv.egovernment.moa.id.BuildException;
+import at.gv.egovernment.moa.id.ParseException;
+import at.gv.egovernment.moa.id.ServiceException;
+import at.gv.egovernment.moa.id.auth.builder.AuthenticationBlockAssertionBuilder;
+import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataAssertionBuilder;
+import at.gv.egovernment.moa.id.auth.builder.CertInfoVerifyXMLSignatureRequestBuilder;
+import at.gv.egovernment.moa.id.auth.builder.CreateXMLSignatureRequestBuilder;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+import at.gv.egovernment.moa.id.auth.builder.GetIdentityLinkFormBuilder;
+import at.gv.egovernment.moa.id.auth.builder.InfoboxReadRequestBuilder;
+import at.gv.egovernment.moa.id.auth.builder.PersonDataBuilder;
+import at.gv.egovernment.moa.id.auth.builder.SAMLArtifactBuilder;
+import at.gv.egovernment.moa.id.auth.builder.SelectBKUFormBuilder;
+import at.gv.egovernment.moa.id.auth.builder.VPKBuilder;
+import at.gv.egovernment.moa.id.auth.builder.VerifyXMLSignatureRequestBuilder;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse;
+import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker;
+import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser;
+import at.gv.egovernment.moa.id.auth.parser.InfoboxReadResponseParser;
+import at.gv.egovernment.moa.id.auth.parser.SAMLArtifactParser;
+import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser;
+import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
+import at.gv.egovernment.moa.id.auth.validator.CreateXMLSignatureResponseValidator;
+import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator;
+import at.gv.egovernment.moa.id.auth.validator.ValidateException;
+import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureResponseValidator;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConfigurationProvider;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.id.util.SSLUtils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.DateTimeUtils;
+import at.gv.egovernment.moa.util.FileUtils;
+
+/**
+ * API for MOA ID Authentication Service.<br>
+ * {@link AuthenticationSession} is stored in a session store and retrieved
+ * by giving the session ID.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class AuthenticationServer implements MOAIDAuthConstants {
+
+ /** single instance */
+ private static AuthenticationServer instance;
+ /** session data store (session ID -> AuthenticationSession) */
+ private static Map sessionStore = new HashMap();
+ /** authentication data store (assertion handle -> AuthenticationData) */
+ private static Map authenticationDataStore = new HashMap();
+ /**
+ * time out in milliseconds used by {@link cleanup} for session store
+ */
+ private long sessionTimeOut = 10*60*1000; // default 10 minutes
+ /**
+ * time out in milliseconds used by {@link cleanup} for authentication data store
+ */
+ private long authDataTimeOut = 2*60*1000; // default 2 minutes
+
+ /**
+ * Returns the single instance of <code>AuthenticationServer</code>.
+ *
+ * @return the single instance of <code>AuthenticationServer</code>
+ */
+ public static AuthenticationServer getInstance() {
+ if (instance == null)
+ instance = new AuthenticationServer();
+ return instance;
+ }
+ /**
+ * Constructor for AuthenticationServer.
+ */
+ public AuthenticationServer() {
+ super();
+ }
+ /**
+ * Processes request to select a BKU.
+ * <br/>Processing depends on value of {@link AuthConfigurationProvider#getBKUSelectionType}.
+ * <br/>For <code>bkuSelectionType==HTMLComplete</code>, a <code>returnURI</code> for the
+ * "BKU Auswahl" service is returned.
+ * <br/>For <code>bkuSelectionType==HTMLSelect</code>, an HTML form for BKU selection is returned.
+ * @param authURL base URL of MOA-ID Auth component
+ * @param target "Gesch&auml;ftsbereich"
+ * @param oaURL online application URL requested
+ * @param bkuSelectionTemplateURL template for BKU selection form to be used
+ * in case of <code>HTMLSelect</code>; may be null
+ * @param templateURL URL providing an HTML template for the HTML form to be used
+ * for call <code>startAuthentication</code>
+ * @return for <code>bkuSelectionType==HTMLComplete</code>, the <code>returnURI</code> for the
+ * "BKU Auswahl" service;
+ * for <code>bkuSelectionType==HTMLSelect</code>, an HTML form for BKU selection
+ * @throws WrongParametersException upon missing parameters
+ * @throws AuthenticationException when the configured BKU selection service cannot be reached,
+ * and when the given bkuSelectionTemplateURL cannot be reached
+ * @throws ConfigurationException on missing configuration data
+ * @throws BuildException while building the HTML form
+ */
+ public String selectBKU(
+ String authURL, String target, String oaURL, String bkuSelectionTemplateURL, String templateURL)
+ throws WrongParametersException, AuthenticationException, ConfigurationException, BuildException {
+
+ if (isEmpty(authURL))
+ throw new WrongParametersException("StartAuthentication", "AuthURL");
+ if (isEmpty(target))
+ throw new WrongParametersException("StartAuthentication", PARAM_TARGET);
+ if (isEmpty(oaURL))
+ throw new WrongParametersException("StartAuthentication", PARAM_OA);
+ if (! authURL.startsWith("https:"))
+ throw new AuthenticationException("auth.07", null);
+ ConnectionParameter bkuConnParam = AuthConfigurationProvider.getInstance().getBKUConnectionParameter();
+ if (bkuConnParam == null)
+ throw new ConfigurationException("config.08", new Object[] {"BKUSelection/ConnectionParameter"});
+ OAAuthParameter oaParam =
+ AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL);
+ if (oaParam == null)
+ throw new AuthenticationException("auth.00", new Object[] {oaURL});
+ AuthenticationSession session = newSession();
+ Logger.info("MOASession " + session.getSessionID() + " angelegt");
+ session.setTarget(target);
+ session.setOAURLRequested(oaURL);
+ session.setPublicOAURLPrefix(oaParam.getPublicURLPrefix());
+ session.setAuthURL(authURL);
+ session.setTemplateURL(templateURL);
+ String returnURL = new DataURLBuilder().buildDataURL(authURL, REQ_START_AUTHENTICATION, session.getSessionID());
+ String bkuSelectionType = AuthConfigurationProvider.getInstance().getBKUSelectionType();
+ if (bkuSelectionType.equals(AuthConfigurationProvider.BKU_SELECTION_TYPE_HTMLCOMPLETE)) {
+ // bkuSelectionType==HTMLComplete
+ String redirectURL = bkuConnParam.getUrl() + "?" + AuthServlet.PARAM_RETURN + "=" + returnURL;
+ return redirectURL;
+ }
+ else {
+ // bkuSelectionType==HTMLSelect
+ String bkuSelectTag;
+ try {
+ bkuSelectTag = readBKUSelectTag(AuthConfigurationProvider.getInstance(), bkuConnParam);
+ }
+ catch (Throwable ex) {
+ throw new AuthenticationException("auth.03", new Object[] {bkuConnParam.getUrl(), ex.toString()}, ex);
+ }
+ String bkuSelectionTemplate = null;
+ if (bkuSelectionTemplateURL != null) {
+ try {
+ bkuSelectionTemplate = new String(FileUtils.readURL(bkuSelectionTemplateURL));
+ }
+ catch (IOException ex) {
+ throw new AuthenticationException("auth.03", new Object[] {bkuSelectionTemplateURL, ex.toString()}, ex);
+ }
+ }
+ String htmlForm = new SelectBKUFormBuilder().build(bkuSelectionTemplate, returnURL, bkuSelectTag);
+ return htmlForm;
+ }
+ }
+ /**
+ * Method readBKUSelectTag.
+ * @param conf the ConfigurationProvider
+ * @param connParam the ConnectionParameter for that connection
+ * @return String
+ * @throws ConfigurationException on config-errors
+ * @throws PKIException on PKI errors
+ * @throws IOException on any data error
+ * @throws GeneralSecurityException on security errors
+ */
+ private String readBKUSelectTag(ConfigurationProvider conf, ConnectionParameter connParam)
+ throws ConfigurationException, PKIException, IOException, GeneralSecurityException {
+
+ if (connParam.isHTTPSURL())
+ return new String(SSLUtils.readHttpsURL(conf, connParam));
+ else
+ return new String(FileUtils.readURL(connParam.getUrl()));
+ }
+ /**
+ * Processes the beginning of an authentication session.
+ * <ul>
+ * <li>Starts an authentication session</li>
+ * <li>Creates an <code>&lt;InfoboxReadRequest&gt;</code></li>
+ * <li>Creates an HTML form for querying the identity link from the
+ * security layer implementation.
+ * <br>Form parameters include
+ * <ul>
+ * <li>the <code>&lt;InfoboxReadRequest&gt;</code></li>
+ * <li>the data URL where the security layer implementation sends it response to</li>
+ * </ul>
+ * </ul>
+ * @param authURL URL of the servlet to be used as data URL
+ * @param target "Gesch&auml;ftsbereich" of the online application requested
+ * @param oaURL online application URL requested
+ * @param bkuURL URL of the "B&uuml;rgerkartenumgebung" to be used;
+ * may be <code>null</code>; in this case, the default location will be used
+ * @param templateURL URL providing an HTML template for the HTML form generated
+ * @return HTML form
+ * @throws AuthenticationException
+ * @see GetIdentityLinkFormBuilder
+ * @see InfoboxReadRequestBuilder
+ */
+ public String startAuthentication(
+ String authURL, String target, String oaURL, String templateURL, String bkuURL, String sessionID)
+ throws WrongParametersException, AuthenticationException, ConfigurationException, BuildException {
+
+ if (isEmpty(sessionID)) {
+ if (isEmpty(authURL))
+ throw new WrongParametersException("StartAuthentication", "AuthURL");
+ if (! authURL.startsWith("https:"))
+ throw new AuthenticationException("auth.07", null);
+ if (isEmpty(target))
+ throw new WrongParametersException("StartAuthentication", PARAM_TARGET);
+ if (isEmpty(oaURL))
+ throw new WrongParametersException("StartAuthentication", PARAM_OA);
+ }
+ AuthenticationSession session;
+ if (sessionID != null)
+ session = getSession(sessionID);
+ else {
+ OAAuthParameter oaParam =
+ AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL);
+ if (oaParam == null)
+ throw new AuthenticationException("auth.00", new Object[] {oaURL});
+ session = newSession();
+ Logger.info("MOASession " + session.getSessionID() + " angelegt");
+ session.setTarget(target);
+ session.setOAURLRequested(oaURL);
+ session.setPublicOAURLPrefix(oaParam.getPublicURLPrefix());
+ session.setAuthURL(authURL);
+ session.setTemplateURL(templateURL);
+ }
+ String infoboxReadRequest = new InfoboxReadRequestBuilder().build();
+ String dataURL = new DataURLBuilder().buildDataURL(
+ session.getAuthURL(), REQ_VERIFY_IDENTITY_LINK, session.getSessionID());
+ String template = null;
+ if (session.getTemplateURL() != null) {
+ try {
+ template = new String(FileUtils.readURL(session.getTemplateURL()));
+ }
+ catch (IOException ex) {
+ throw new AuthenticationException("auth.03", new Object[] {session.getTemplateURL(), ex.toString()}, ex);
+ }
+ }
+ String certInfoRequest = new CertInfoVerifyXMLSignatureRequestBuilder().build();
+ String certInfoDataURL = new DataURLBuilder().buildDataURL(
+ session.getAuthURL(), REQ_START_AUTHENTICATION, session.getSessionID());
+ String htmlForm = new GetIdentityLinkFormBuilder().build(
+ template, bkuURL, infoboxReadRequest, dataURL, certInfoRequest, certInfoDataURL);
+ return htmlForm;
+ }
+ /**
+ * Processes an <code>&lt;InfoboxReadResponse&gt;</code> sent by the
+ * security layer implementation.<br>
+ * <ul>
+ * <li>Validates given <code>&lt;InfoboxReadResponse&gt;</code></li>
+ * <li>Parses identity link enclosed in <code>&lt;InfoboxReadResponse&gt;</code></li>
+ * <li>Verifies identity link by calling the MOA SP component</li>
+ * <li>Checks certificate authority of identity link</li>
+ * <li>Stores identity link in the session</li>
+ * <li>Creates an authentication block to be signed by the user</li>
+ * <li>Creates and returns a <code>&lt;CreateXMLSignatureRequest&gt;</code>
+ * containg the authentication block, meant to be returned to the
+ * security layer implementation</li>
+ * </ul>
+ *
+ * @param sessionID ID of associated authentication session data
+ * @param xmlInfoboxReadResponse String representation of the
+ * <code>&lt;InfoboxReadResponse&gt;</code>
+ * @return String representation of the <code>&lt;CreateXMLSignatureRequest&gt;</code>
+ */
+ public String verifyIdentityLink (String sessionID, String xmlInfoboxReadResponse)
+ throws AuthenticationException, ParseException, ConfigurationException, ValidateException, ServiceException, WrongParametersException {
+
+ if (isEmpty(sessionID))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID);
+ if (isEmpty(xmlInfoboxReadResponse))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE);
+ AuthenticationSession session = getSession(sessionID);
+ if (session.getTimestampIdentityLink() != null)
+ throw new AuthenticationException("auth.01", new Object[] {sessionID});
+ session.setTimestampIdentityLink();
+ AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
+ // parses the <InfoboxReadResponse>
+ IdentityLink identityLink = new InfoboxReadResponseParser(xmlInfoboxReadResponse).
+ parseIdentityLink();
+ // validates the identity link
+ IdentityLinkValidator.getInstance().validate(identityLink);
+ // builds a <VerifyXMLSignatureRequest> for a call of MOA-SP
+ Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder().build(
+ identityLink, authConf.getMoaSpIdentityLinkTrustProfileID());
+ // debug output
+ debugOutputXMLFile("VerifyIdentityLinkRequest.xml", domVerifyXMLSignatureRequest);
+ // invokes the call
+ Element domVerifyXMLSignatureResponse = new SignatureVerificationInvoker().
+ verifyXMLSignature(domVerifyXMLSignatureRequest);
+ // parses the <VerifyXMLSignatureResponse>
+ VerifyXMLSignatureResponse verifyXMLSignatureResponse =
+ new VerifyXMLSignatureResponseParser(domVerifyXMLSignatureResponse).parseData();
+ // debug output
+ debugOutputXMLFile("VerifyIdentityLinkResponse.xml", domVerifyXMLSignatureResponse);
+ // validates the <VerifyXMLSignatureResponse>
+ VerifyXMLSignatureResponseValidator.getInstance().validate(
+ verifyXMLSignatureResponse,
+ authConf.getIdentityLinkX509SubjectNames(),
+ VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK);
+
+ session.setIdentityLink(identityLink);
+ // builds the AUTH-block
+ String authBlock = buildAuthenticationBlock(session);
+ session.setAuthBlock(authBlock);
+ // builds the <CreateXMLSignatureRequest>
+ String[] transformInfos = authConf.getTransformsInfos();
+ String createXMLSignatureRequest = new CreateXMLSignatureRequestBuilder().
+ build(authBlock, transformInfos);
+ return createXMLSignatureRequest;
+ }
+ /**
+ * Builds an authentication block <code>&lt;saml:Assertion&gt;</code> from given session data.
+ * @param session authentication session
+ * @return <code>&lt;saml:Assertion&gt;</code> as a String
+ */
+ private String buildAuthenticationBlock(AuthenticationSession session) {
+ IdentityLink identityLink = session.getIdentityLink();
+ String issuer = identityLink.getGivenName() + " " + identityLink.getFamilyName();
+ String issueInstant = DateTimeUtils.buildDateTime(Calendar.getInstance());
+ String authURL = session.getAuthURL();
+ String target = session.getTarget();
+ String oaURL = session.getPublicOAURLPrefix();
+ String authBlock = new AuthenticationBlockAssertionBuilder().
+ build(issuer, issueInstant, authURL, target, oaURL);
+ return authBlock;
+ }
+ /**
+ * Processes a <code>&lt;CreateXMLSignatureResponse&gt;</code> sent by the
+ * security layer implementation.<br>
+ * <ul>
+ * <li>Validates given <code>&lt;CreateXMLSignatureResponse&gt;</code></li>
+ * <li>Parses <code>&lt;CreateXMLSignatureResponse&gt;</code> for error codes</li>
+ * <li>Parses authentication block enclosed in
+ * <code>&lt;CreateXMLSignatureResponse&gt;</code></li>
+ * <li>Verifies authentication block by calling the MOA SP component</li>
+ * <li>Creates authentication data</li>
+ * <li>Creates a corresponding SAML artifact</li>
+ * <li>Stores authentication data in the authentication data store
+ * indexed by the SAML artifact</li>
+ * <li>Deletes authentication session</li>
+ * <li>Returns the SAML artifact, encoded BASE64</li>
+ * </ul>
+ *
+ * @param sessionID session ID of the running authentication session
+ * @param xmlCreateXMLSignatureReadResponse String representation of the
+ * <code>&lt;CreateXMLSignatureResponse&gt;</code>
+ * @return SAML artifact needed for retrieving authentication data, encoded BASE64
+ */
+ public String verifyAuthenticationBlock(
+ String sessionID, String xmlCreateXMLSignatureReadResponse)
+ throws AuthenticationException, BuildException, ParseException, ConfigurationException, ServiceException, ValidateException, WrongParametersException {
+
+ if (isEmpty(sessionID))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID);
+ if (isEmpty(xmlCreateXMLSignatureReadResponse))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE);
+ AuthenticationSession session = getSession(sessionID);
+ AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
+ // parses <CreateXMLSignatureResponse>
+ CreateXMLSignatureResponse csresp =
+ new CreateXMLSignatureResponseParser(xmlCreateXMLSignatureReadResponse).parseResponse();
+ // validates <CreateXMLSignatureResponse>
+ new CreateXMLSignatureResponseValidator().validate(csresp, session.getTarget(), session.getPublicOAURLPrefix());
+ // builds a <VerifyXMLSignatureRequest> for a MOA-SPSS call
+ String[] vtids = authConf.getMoaSpAuthBlockVerifyTransformsInfoIDs();
+ String tpid = authConf.getMoaSpAuthBlockTrustProfileID();
+ Element domVsreq = new VerifyXMLSignatureRequestBuilder().build(csresp, vtids, tpid);
+ // debug output
+ AuthenticationServer.debugOutputXMLFile("VerifyAuthenticationBlockRequest.xml", domVsreq);
+ // invokes the call
+ Element domVsresp = new SignatureVerificationInvoker().verifyXMLSignature(domVsreq);
+ // parses the <VerifyXMLSignatureResponse>
+ VerifyXMLSignatureResponse vsresp = new VerifyXMLSignatureResponseParser(domVsresp).parseData();
+ // debug output
+ AuthenticationServer.debugOutputXMLFile("VerifyAuthenticationBlockResponse.xml", domVsresp);
+ // validates the <VerifyXMLSignatureResponse>
+ VerifyXMLSignatureResponseValidator.getInstance().validate(
+ vsresp, null,VerifyXMLSignatureResponseValidator.CHECK_AUTH_BLOCK);
+ // compares the public keys from the identityLink with the AuthBlock
+ VerifyXMLSignatureResponseValidator.getInstance().validateCertificate(vsresp, session.getIdentityLink());
+
+ // builds authentication data and stores it together with a SAML artifact
+ AuthenticationData authData = buildAuthenticationData(session, vsresp);
+ String samlArtifact = new SAMLArtifactBuilder().build(session.getAuthURL(), session.getSessionID());
+ storeAuthenticationData(samlArtifact, authData);
+ // invalidates the authentication session
+ sessionStore.remove(sessionID);
+ Logger.info("Anmeldedaten zu MOASession " + sessionID + " angelegt, SAML Artifakt " + samlArtifact);
+ return samlArtifact;
+ }
+ /**
+ * Builds the AuthenticationData object together with the
+ * corresponding <code>&lt;saml:Assertion&gt;</code>
+ * @param session authentication session
+ * @param verifyXMLSigResp VerifyXMLSignatureResponse from MOA-SP
+ * @return AuthenticationData object
+ * @throws ConfigurationException while accessing configuration data
+ * @throws BuildException while building the <code>&lt;saml:Assertion&gt;</code>
+ */
+ private AuthenticationData buildAuthenticationData(
+ AuthenticationSession session,
+ VerifyXMLSignatureResponse verifyXMLSigResp)
+ throws ConfigurationException, BuildException {
+
+ IdentityLink identityLink = session.getIdentityLink();
+ AuthenticationData authData = new AuthenticationData();
+ authData.setMajorVersion(1);
+ authData.setMinorVersion(0);
+ authData.setAssertionID(Random.nextRandom());
+ authData.setIssuer(session.getAuthURL());
+ authData.setIssueInstant(DateTimeUtils.buildDateTime(Calendar.getInstance()));
+ String vpkBase64 = new VPKBuilder().buildVPK(
+ identityLink.getIdentificationValue(), identityLink.getDateOfBirth(), session.getTarget());
+ authData.setVPK(vpkBase64);
+ authData.setGivenName(identityLink.getGivenName());
+ authData.setFamilyName(identityLink.getFamilyName());
+ authData.setDateOfBirth(identityLink.getDateOfBirth());
+ authData.setQualifiedCertificate(verifyXMLSigResp.isQualifiedCertificate());
+ authData.setPublicAuthority(verifyXMLSigResp.isPublicAuthority());
+ authData.setPublicAuthorityCode(verifyXMLSigResp.getPublicAuthorityCode());
+ OAAuthParameter oaParam =
+ AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
+ session.getPublicOAURLPrefix());
+ String prPerson = new PersonDataBuilder().build(
+ identityLink, oaParam.getProvideZMRZahl());
+
+ try {
+ String ilAssertion =
+ oaParam.getProvideIdentityLink() ? DOMUtils.serializeNode(identityLink.getSamlAssertion()) : "";
+ String authBlock = oaParam.getProvideAuthBlock() ? session.getAuthBlock() : "";
+ String samlAssertion = new AuthenticationDataAssertionBuilder().build(
+ authData, prPerson, authBlock, ilAssertion);
+ authData.setSamlAssertion(samlAssertion);
+ return authData;
+ }
+ catch (Throwable ex) {
+ throw new BuildException(
+ "builder.00",
+ new Object[] { "AuthenticationData", ex.toString() },
+ ex);
+ }
+ }
+ /**
+ * Retrieves <code>AuthenticationData</code> indexed by the SAML artifact.
+ * The <code>AuthenticationData</code> is deleted from the store upon end of this call.
+ *
+ * @return <code>AuthenticationData</code>
+ */
+ public AuthenticationData getAuthenticationData(String samlArtifact) throws AuthenticationException {
+ String assertionHandle;
+ try {
+ assertionHandle = new SAMLArtifactParser(samlArtifact).parseAssertionHandle();
+ }
+ catch (ParseException ex) {
+ throw new AuthenticationException("1205", new Object[] {samlArtifact, ex.toString()});
+ }
+ AuthenticationData authData = null;
+ synchronized (authenticationDataStore) {
+ authData = (AuthenticationData)authenticationDataStore.get(assertionHandle);
+ if (authData == null) {
+ Logger.error("Assertion not found for SAML Artifact: " + samlArtifact);
+ throw new AuthenticationException("1206", new Object[] {samlArtifact});
+ }
+ authenticationDataStore.remove(assertionHandle);
+ }
+ long now = new Date().getTime();
+ if (now - authData.getTimestamp().getTime() > authDataTimeOut)
+ throw new AuthenticationException("1207", new Object[] {samlArtifact});
+ Logger.debug("Assertion delivered for SAML Artifact: " + samlArtifact);
+ return authData;
+ }
+ /**
+ * Stores authentication data indexed by the assertion handle contained in the
+ * given saml artifact.
+ * @param samlArtifact SAML artifact
+ * @param authData authentication data
+ * @throws AuthenticationException when SAML artifact is invalid
+ */
+ private void storeAuthenticationData(String samlArtifact, AuthenticationData authData)
+ throws AuthenticationException {
+
+ try {
+ SAMLArtifactParser parser = new SAMLArtifactParser(samlArtifact);
+ // check type code 0x0001
+ byte[] typeCode = parser.parseTypeCode();
+ if (typeCode[0] != 0 || typeCode[1] != 1)
+ throw new AuthenticationException("auth.06", new Object[] {samlArtifact});
+ String assertionHandle = parser.parseAssertionHandle();
+ synchronized(authenticationDataStore) {
+ Logger.debug("Assertion stored for SAML Artifact: " + samlArtifact);
+ authenticationDataStore.put(assertionHandle, authData);
+ }
+ }
+ catch (AuthenticationException ex) {
+ throw ex;
+ }
+ catch (Throwable ex) {
+ throw new AuthenticationException("auth.06", new Object[] {samlArtifact});
+ }
+ }
+ /**
+ * Creates a new session and puts it into the session store.
+ *
+ * @param id Session ID
+ * @return AuthenticationSession created
+ * @exception AuthenticationException
+ * thrown when an <code>AuthenticationSession</code> is running
+ * already for the given session ID
+ */
+ private static AuthenticationSession newSession() throws AuthenticationException {
+ String sessionID = Random.nextRandom();
+ AuthenticationSession newSession = new AuthenticationSession(sessionID);
+ synchronized (sessionStore) {
+ AuthenticationSession session = (AuthenticationSession)sessionStore.get(sessionID);
+ if (session != null)
+ throw new AuthenticationException("auth.01", new Object[] { sessionID });
+ sessionStore.put(sessionID, newSession);
+ }
+ return newSession;
+ }
+ /**
+ * Retrieves a session from the session store.
+ *
+ * @param id session ID
+ * @return <code>AuthenticationSession</code> stored with given session ID,
+ * <code>null</code> if session ID unknown
+ */
+ public static AuthenticationSession getSession(String id) throws AuthenticationException {
+ AuthenticationSession session = (AuthenticationSession)sessionStore.get(id);
+ if (session == null)
+ throw new AuthenticationException("auth.02", new Object[] { id });
+ return session;
+ }
+ /**
+ * Cleans up expired session and authentication data stores.
+ */
+ public void cleanup() {
+ long now = new Date().getTime();
+ synchronized(sessionStore) {
+ Set keys = new HashSet(sessionStore.keySet());
+ for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
+ String sessionID = (String) iter.next();
+ AuthenticationSession session = (AuthenticationSession) sessionStore.get(sessionID);
+ if (now - session.getTimestampStart().getTime() > sessionTimeOut) {
+ Logger.info(MOAIDMessageProvider.getInstance().getMessage("cleaner.02", new Object[] {sessionID}));
+ sessionStore.remove(sessionID);
+ }
+ }
+ }
+ synchronized(authenticationDataStore) {
+ Set keys = new HashSet(authenticationDataStore.keySet());
+ for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
+ String samlArtifact = (String) iter.next();
+ AuthenticationData authData = (AuthenticationData) authenticationDataStore.get(samlArtifact);
+ if (now - authData.getTimestamp().getTime() > authDataTimeOut) {
+ Logger.info(MOAIDMessageProvider.getInstance().getMessage("cleaner.03", new Object[] {samlArtifact}));
+ authenticationDataStore.remove(samlArtifact);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the sessionTimeOut.
+ * @param sessionTimeOut time out in seconds
+ */
+ public void setSecondsSessionTimeOut(long seconds) {
+ sessionTimeOut = 1000 * seconds;
+ }
+ /**
+ * Sets the authDataTimeOut.
+ * @param authDataTimeOut time out in seconds
+ */
+ public void setSecondsAuthDataTimeOut(long seconds) {
+ authDataTimeOut = 1000 * seconds;
+ }
+
+ /**
+ * Checks a parameter.
+ * @param param parameter
+ * @return true if the parameter is null or empty
+ */
+ private boolean isEmpty(String param) {
+ return param == null || param.length() == 0;
+ }
+
+ /**
+ * Writes an XML structure to file for debugging purposes, encoding UTF-8.
+ *
+ * @param filename file name
+ * @param rootElem root element in DOM tree
+ */
+ public static void debugOutputXMLFile(String filename, Element rootElem) {
+ if (Logger.isDebugEnabled(DEBUG_OUTPUT_HIERARCHY)) {
+ try {
+ String xmlString = new String(DOMUtils.serializeNode(rootElem));
+ debugOutputXMLFile(filename, xmlString);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+ /**
+ * Writes an XML structure to file for debugging purposes, encoding UTF-8.
+ *
+ * @param filename file name
+ * @param xmlString XML string
+ */
+ public static void debugOutputXMLFile(String filename, String xmlString) {
+ if (Logger.isDebugEnabled(DEBUG_OUTPUT_HIERARCHY)) {
+ try {
+ java.io.OutputStream fout = new java.io.FileOutputStream(filename);
+ byte[] xmlData = xmlString.getBytes("UTF-8");
+ fout.write(xmlData);
+ fout.close();
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java b/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java
new file mode 100644
index 000000000..7e5ed6ec7
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java
@@ -0,0 +1,52 @@
+package at.gv.egovernment.moa.id.auth;
+
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Thread cleaning the <code>AuthenticationServer</code> session store
+ * and authentication data store from garbage.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class AuthenticationSessionCleaner implements Runnable {
+
+ /** interval the <code>AuthenticationSessionCleaner</code> is run in */
+ private static final long SESSION_CLEANUP_INTERVAL = 30 * 60; // 30 min
+
+ /**
+ * Runs the thread. Cleans the <code>AuthenticationServer</code> session store
+ * and authentication data store from garbage, then sleeps for given interval, and restarts.
+ */
+ public void run() {
+ while (true) {
+ try {
+ Logger.debug("AuthenticationSessionCleaner run");
+ AuthenticationServer.getInstance().cleanup();
+ }
+ catch (Exception e) {
+ Logger.error(MOAIDMessageProvider.getInstance().getMessage("cleaner.01", null), e);
+ }
+ try {
+ Thread.sleep(SESSION_CLEANUP_INTERVAL * 1000);
+ }
+ catch (InterruptedException e) {
+ }
+ }
+ }
+
+ /**
+ * start the sessionCleaner
+ */
+ public static void start() {
+ // start the session cleanup thread
+ Thread sessionCleaner =
+ new Thread(new AuthenticationSessionCleaner());
+ sessionCleaner.setName("SessionCleaner");
+ sessionCleaner.setDaemon(true);
+ sessionCleaner.setPriority(Thread.MIN_PRIORITY);
+ sessionCleaner.start();
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java b/id.server/src/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
new file mode 100644
index 000000000..ddba20049
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
@@ -0,0 +1,53 @@
+package at.gv.egovernment.moa.id.auth;
+
+/**
+ * Constants used throughout moa-id-auth component.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public interface MOAIDAuthConstants {
+
+ /** servlet parameter &quot;Target&quot; */
+ public static final String PARAM_TARGET = "Target";
+ /** servlet parameter &quot;OA&quot; */
+ public static final String PARAM_OA = "OA";
+ /** servlet parameter &quot;bkuURI&quot; */
+ public static final String PARAM_BKU = "bkuURI";
+ /** servlet parameter &quot;BKUSelectionTemplate&quot; */
+ public static final String PARAM_BKUTEMPLATE = "BKUSelectionTemplate";
+ /** servlet parameter &quot;returnURI&quot; */
+ public static final String PARAM_RETURN = "returnURI";
+ /** servlet parameter &quot;Template&quot; */
+ public static final String PARAM_TEMPLATE = "Template";
+ /** servlet parameter &quot;MOASessionID&quot; */
+ public static final String PARAM_SESSIONID = "MOASessionID";
+ /** servlet parameter &quot;XMLResponse&quot; */
+ public static final String PARAM_XMLRESPONSE = "XMLResponse";
+ /** servlet parameter &quot;SAMLArtifact&quot; */
+ public static final String PARAM_SAMLARTIFACT = "SAMLArtifact";
+ /** Request name {@link at.gv.egovernment.moa.id.auth.servlet.StartAuthenticationServlet} is mapped to */
+ public static final String REQ_START_AUTHENTICATION = "StartAuthentication";
+ /** Request name {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet} is mapped to */
+ public static final String REQ_VERIFY_IDENTITY_LINK = "VerifyIdentityLink";
+ /** Request name {@link at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet} is mapped to */
+ public static final String REQ_VERIFY_AUTH_BLOCK = "VerifyAuthBlock";
+ /** Logging hierarchy used for controlling debug output of XML structures to files */
+ public static final String DEBUG_OUTPUT_HIERARCHY = "moa.id.auth";
+ /** Header Name for controlling the caching mechanism of the browser */
+ public static final String HEADER_EXPIRES = "Expires";
+ /** Header Value for controlling the caching mechanism of the browser */
+ public static final String HEADER_VALUE_EXPIRES = "Sat, 6 May 1995 12:00:00 GMT";
+ /** Header Name for controlling the caching mechanism of the browser */
+ public static final String HEADER_PRAGMA = "Pragma";
+ /** Header Value for controlling the caching mechanism of the browser */
+ public static final String HEADER_VALUE_PRAGMA = "no-cache";
+ /** Header Name for controlling the caching mechanism of the browser */
+ public static final String HEADER_CACHE_CONTROL = "Cache-control";
+ /** Header Value for controlling the caching mechanism of the browser */
+ public static final String HEADER_VALUE_CACHE_CONTROL = "no-store, no-cache, must-revalidate";
+ /** Header Value for controlling the caching mechanism of the browser */
+ public static final String HEADER_VALUE_CACHE_CONTROL_IE = "post-check=0, pre-check=0";
+
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java b/id.server/src/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java
new file mode 100644
index 000000000..f9bec8b76
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java
@@ -0,0 +1,118 @@
+package at.gv.egovernment.moa.id.auth;
+
+import iaik.pki.PKIException;
+import iaik.pki.jsse.IAIKX509TrustManager;
+
+import java.security.GeneralSecurityException;
+
+import java.io.IOException;
+
+import javax.net.ssl.SSLSocketFactory;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.iaik.config.LoggerConfigImpl;
+import at.gv.egovernment.moa.id.util.AxisSecureSocketFactory;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.id.util.SSLUtils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.logging.LoggingContext;
+import at.gv.egovernment.moa.logging.LoggingContextManager;
+import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider;
+import at.gv.egovernment.moa.spss.server.iaik.config.IaikConfigurator;
+
+/**
+ * Web application initializer
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class MOAIDAuthInitializer {
+
+ /** a boolean identifying if the MOAIDAuthInitializer has been startet */
+ public static boolean initialized = false;
+
+
+
+ /**
+ * Initializes the web application components which need initialization:
+ * logging, JSSE, MOA-ID Auth configuration, Axis, session cleaner.
+ */
+ public static void initialize()
+ throws ConfigurationException, PKIException, IOException, GeneralSecurityException {
+ if (initialized)
+ return;
+ initialized=true;
+ Logger.setHierarchy("moa.id.auth");
+ // Restricts TLS cipher suites
+ System.setProperty("https.cipherSuites", "SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_MD5,SSL_RSA_WITH_3DES_EDE_CBC_SHA");
+ // load some jsse classes so that the integrity of the jars can be verified
+ // before the iaik jce is installed as the security provider
+ // this workaround is only needed when sun jsse is used in conjunction with
+ // iaik-jce (on jdk1.3)
+ ClassLoader cl = MOAIDAuthInitializer.class.getClassLoader();
+ try {
+ cl.loadClass("javax.security.cert.Certificate"); // from jcert.jar
+ }
+ catch (ClassNotFoundException e) {
+ Logger.warn(MOAIDMessageProvider.getInstance().getMessage("init.01", null), e);
+ }
+
+ // Initializes SSLSocketFactory store
+ SSLUtils.initialize();
+
+ // Loads the configuration
+ AuthConfigurationProvider authConf = AuthConfigurationProvider.reload();
+ ConnectionParameter moaSPConnParam = authConf.getMoaSpConnectionParameter();
+
+ // If MOA-SP API calls: loads MOA-SP configuration and configures IAIK
+ if (moaSPConnParam == null) {
+ try {
+ LoggingContextManager.getInstance().setLoggingContext(
+ new LoggingContext("startup"));
+ ConfigurationProvider config = ConfigurationProvider.getInstance();
+ new IaikConfigurator().configure(config);
+ }
+ catch (at.gv.egovernment.moa.spss.server.config.ConfigurationException ex) {
+ throw new ConfigurationException("config.10", new Object[] { ex.toString() }, ex);
+ }
+ }
+
+ // Initializes IAIKX509TrustManager logging
+ String log4jConfigURL = System.getProperty("log4j.configuration");
+ if (log4jConfigURL != null) {
+ IAIKX509TrustManager.initLog(new LoggerConfigImpl(log4jConfigURL));
+ }
+
+ // Initializes the Axis secure socket factory for use in calling the MOA-SP web service
+ if (moaSPConnParam != null && moaSPConnParam.isHTTPSURL()) {
+ SSLSocketFactory ssf = SSLUtils.getSSLSocketFactory(authConf, moaSPConnParam);
+ AxisSecureSocketFactory.initialize(ssf);
+ }
+
+ // sets the authentication session and authentication data time outs
+ String param = authConf.getGenericConfigurationParameter(AuthConfigurationProvider.AUTH_SESSION_TIMEOUT_PROPERTY);
+ if (param != null) {
+ long sessionTimeOut = 0;
+ try { sessionTimeOut = new Long(param).longValue(); }
+ catch (NumberFormatException ex) {
+ Logger.error(MOAIDMessageProvider.getInstance().getMessage("config.05", new Object[] {AuthConfigurationProvider.AUTH_SESSION_TIMEOUT_PROPERTY}));
+ }
+ if (sessionTimeOut > 0)
+ AuthenticationServer.getInstance().setSecondsSessionTimeOut(sessionTimeOut);
+ }
+ param = authConf.getGenericConfigurationParameter(AuthConfigurationProvider.AUTH_DATA_TIMEOUT_PROPERTY);
+ if (param != null) {
+ long authDataTimeOut = 0;
+ try { authDataTimeOut = new Long(param).longValue(); }
+ catch (NumberFormatException ex) {
+ Logger.error(MOAIDMessageProvider.getInstance().getMessage("config.05", new Object[] {AuthConfigurationProvider.AUTH_DATA_TIMEOUT_PROPERTY}));
+ }
+ if (authDataTimeOut > 0)
+ AuthenticationServer.getInstance().setSecondsAuthDataTimeOut(authDataTimeOut);
+ }
+
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/WrongParametersException.java b/id.server/src/at/gv/egovernment/moa/id/auth/WrongParametersException.java
new file mode 100644
index 000000000..3ce2798ea
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/WrongParametersException.java
@@ -0,0 +1,21 @@
+package at.gv.egovernment.moa.id.auth;
+
+import at.gv.egovernment.moa.id.MOAIDException;
+
+/**
+ * Exception thrown when the <code>AuthenticationServer</code> API is
+ * called with wrong parameters provided.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class WrongParametersException extends MOAIDException {
+
+ /**
+ * Constructor
+ */
+ public WrongParametersException(String call, String parameter) {
+ super("auth.05", new Object[] {call, parameter});
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/AuthenticationBlockAssertionBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/AuthenticationBlockAssertionBuilder.java
new file mode 100644
index 000000000..4babf948c
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/AuthenticationBlockAssertionBuilder.java
@@ -0,0 +1,56 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import java.text.MessageFormat;
+
+import at.gv.egovernment.moa.util.Constants;
+
+/**
+ * Builder for the authentication block <code>&lt;saml:Assertion&gt;</code>
+ * to be included in a <code>&lt;CreateXMLSignatureResponse&gt;</code>.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class AuthenticationBlockAssertionBuilder implements Constants {
+ /** private static String nl contains the NewLine representation in Java*/
+ private static String nl = "\n";
+ /** private static String AUTH_BLOCK contains an XML-Auth-Block-Template */
+ private static String AUTH_BLOCK =
+ "<saml:Assertion xmlns:saml=''" + SAML_NS_URI + "'' MajorVersion=''1'' MinorVersion=''0'' AssertionID=''any'' Issuer=''{0}'' IssueInstant=''{1}''>" + nl +
+ " <saml:AttributeStatement>" + nl +
+ " <saml:Subject>" + nl +
+ " <saml:NameIdentifier>{2}</saml:NameIdentifier>" + nl +
+ " </saml:Subject>" + nl +
+ " <saml:Attribute AttributeName=''Geschäftsbereich'' AttributeNamespace=''" + MOA_NS_URI + "''>" + nl +
+ " <saml:AttributeValue>{3}</saml:AttributeValue>" + nl +
+ " </saml:Attribute>" + nl +
+ " <saml:Attribute AttributeName=''OA'' AttributeNamespace=''" + MOA_NS_URI + "''>" + nl +
+ " <saml:AttributeValue>{4}</saml:AttributeValue>" + nl +
+ " </saml:Attribute>" + nl +
+ " </saml:AttributeStatement>" + nl +
+ "</saml:Assertion>";
+
+ /**
+ * Constructor for AuthenticationBlockAssertionBuilder.
+ */
+ public AuthenticationBlockAssertionBuilder() {
+ super();
+ }
+ /**
+ * Builds the authentication block <code>&lt;saml:Assertion&gt;</code>.
+ *
+ * @param issuer authentication block issuer; <code>"GivenName FamilyName"</code>
+ * @param issueInstant current timestamp
+ * @param authURL URL of MOA-ID authentication component
+ * @param target "Gesch&auml;ftsbereich"
+ * @param oaURL public URL of online application requested
+ * @return String representation of authentication block
+ * <code>&lt;saml:Assertion&gt;</code> built
+ */
+ public String build(String issuer, String issueInstant, String authURL, String target, String oaURL) {
+ String assertion = MessageFormat.format(
+ AUTH_BLOCK, new Object[] { issuer, issueInstant, authURL, target, oaURL });
+ return assertion;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataAssertionBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataAssertionBuilder.java
new file mode 100644
index 000000000..fd7cb1a9d
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataAssertionBuilder.java
@@ -0,0 +1,114 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import java.text.MessageFormat;
+
+import at.gv.egovernment.moa.id.BuildException;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+import at.gv.egovernment.moa.util.Constants;
+
+/**
+ * Builder for the authentication data <code>&lt;saml:Assertion&gt;</code>
+ * to be provided by the MOA ID Auth component.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class AuthenticationDataAssertionBuilder implements Constants {
+ /** private static String NL contains the NewLine representation in Java*/
+ private static final String NL = "\n";
+ /**
+ * XML template for the <code>&lt;saml:Assertion&gt;</code> to be built
+ */
+ private static final String AUTH_DATA =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + NL +
+ "<saml:Assertion xmlns:saml=''" + SAML_NS_URI + "'' xmlns:pr=''" + PD_NS_URI + "'' xmlns:xsi=''" + XSI_NS_URI + "''" +
+ " MajorVersion=''1'' MinorVersion=''0'' AssertionID=''{0}'' Issuer=''{1}'' IssueInstant=''{2}''>" + NL +
+ " <saml:AttributeStatement>" + NL +
+ " <saml:Subject>" + NL +
+ " <saml:NameIdentifier NameQualifier=''http://reference.e-government.gv.at/names/vpk/20020221#''>{3}</saml:NameIdentifier>" + NL +
+ " <saml:SubjectConfirmation>" + NL +
+ " <saml:ConfirmationMethod>" + MOA_NS_URI + "cm</saml:ConfirmationMethod>" + NL +
+ " <saml:SubjectConfirmationData>{4}{5}</saml:SubjectConfirmationData>" + NL +
+ " </saml:SubjectConfirmation>" + NL +
+ " </saml:Subject>" + NL +
+ " <saml:Attribute AttributeName=''PersonData'' AttributeNamespace=''" + PD_NS_URI + "''>" + NL +
+ " <saml:AttributeValue>{6}</saml:AttributeValue>" + NL +
+ " </saml:Attribute>" + NL +
+ " <saml:Attribute AttributeName=''isQualifiedCertificate'' AttributeNamespace=''" + MOA_NS_URI + "''>" + NL +
+ " <saml:AttributeValue>{7}</saml:AttributeValue>" + NL +
+ " </saml:Attribute>" + NL +
+ "{8}" +
+ " </saml:AttributeStatement>" + NL +
+ "</saml:Assertion>";
+ /**
+ * XML template for the <code>&lt;saml:Attribute&gt;</code> named <code>"isPublicAuthority"</code>,
+ * to be inserted into the <code>&lt;saml:Assertion&gt;</code>
+ */
+ private static final String PUBLIC_AUTHORITY_ATT =
+ " <saml:Attribute AttributeName=''isPublicAuthority'' AttributeNamespace=''urn:oid:1.2.40.0.10.1.1.1''>" + NL +
+ " <saml:AttributeValue>{0}</saml:AttributeValue>" + NL +
+ " </saml:Attribute>" + NL;
+
+ /**
+ * Constructor for AuthenticationDataAssertionBuilder.
+ */
+ public AuthenticationDataAssertionBuilder() {
+ super();
+ }
+
+ /**
+ * Builds the authentication data <code>&lt;saml:Assertion&gt;</code>.
+ *
+ * @param authData the <code>AuthenticationData</code> to build the
+ * <code>&lt;saml:Assertion&gt;</code> from
+ * @param xmlPersonData <code>lt;pr:Person&gt;</code> element as a String
+ * @param xmlAuthBlock authentication block to be included in a
+ * <code>lt;saml:SubjectConfirmationData&gt;</code> element; may include
+ * the <code>"ZMR-Zahl"</code> or not; may be empty
+ * @param xmlIdentityLink the IdentityLink
+ * @return the <code>&lt;saml:Assertion&gt;</code>
+ * @throws BuildException if an error occurs during the build process
+ */
+ public String build(
+ AuthenticationData authData,
+ String xmlPersonData,
+ String xmlAuthBlock,
+ String xmlIdentityLink) throws BuildException {
+
+ String isQualifiedCertificate = authData.isQualifiedCertificate() ? "true" : "false";
+ String publicAuthorityAttribute = "";
+ if (authData.isPublicAuthority()) {
+ String publicAuthorityIdentification = authData.getPublicAuthorityCode();
+ if (publicAuthorityIdentification == null)
+ publicAuthorityIdentification = "True";
+ publicAuthorityAttribute = MessageFormat.format(
+ PUBLIC_AUTHORITY_ATT, new Object[] { publicAuthorityIdentification });
+ }
+
+ String assertion = MessageFormat.format(AUTH_DATA, new Object[] {
+ authData.getAssertionID(),
+ authData.getIssuer(),
+ authData.getIssueInstant(),
+ authData.getVPK(),
+ removeXMLDeclaration(xmlAuthBlock),
+ removeXMLDeclaration(xmlIdentityLink),
+ removeXMLDeclaration(xmlPersonData),
+ isQualifiedCertificate,
+ publicAuthorityAttribute});
+ return assertion;
+ }
+
+ /**
+ * Removes the XML declaration from an XML expression.
+ * @param xmlString XML expression as String
+ * @return XML expression, XML declaration removed
+ */
+ private String removeXMLDeclaration(String xmlString) {
+ if (xmlString.startsWith("<?xml")) {
+ int firstElement = xmlString.indexOf("<", 1);
+ return xmlString.substring(firstElement);
+ }
+ else return xmlString;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/Builder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/Builder.java
new file mode 100644
index 000000000..e5bbaa585
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/Builder.java
@@ -0,0 +1,30 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import at.gv.egovernment.moa.id.BuildException;
+
+/**
+ * Base class for HTML/XML builders providing commonly useful functions.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class Builder {
+
+ /**
+ * Replaces a special tag in an XML or HTML template by a value.
+ * @param htmlTemplate template
+ * @param tag special tag
+ * @param value value replacing the tag
+ * @return XML or HTML code, the tag replaced
+ * @throws BuildException when template does not contain the tag
+ */
+ protected String replaceTag(String template, String tag, String value) throws BuildException {
+ int index = template.indexOf(tag);
+ if (index < 0)
+ throw new BuildException(
+ "builder.01",
+ new Object[] {"&lt;" + tag.substring(1, tag.length() - 1) + "&gt;"});
+ return template.substring(0, index) + value + template.substring(index + tag.length());
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/CertInfoVerifyXMLSignatureRequestBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/CertInfoVerifyXMLSignatureRequestBuilder.java
new file mode 100644
index 000000000..5ceb1d1c0
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/CertInfoVerifyXMLSignatureRequestBuilder.java
@@ -0,0 +1,51 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import java.io.IOException;
+
+import at.gv.egovernment.moa.id.BuildException;
+import at.gv.egovernment.moa.util.FileUtils;
+
+/**
+ * Builder for the <code>&lt;VerifyXMLSignatureRequest&gt;</code> structure
+ * used for presenting certificate information in the secure viewer of the security layer implementation.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class CertInfoVerifyXMLSignatureRequestBuilder extends Builder {
+
+ /** special tag in the VerifyXMLRequest template to be substituted for a <code>&lt;dsig:Signature&gt;</code> */
+ private static final String SIGNATURE_TAG = "<dsig:Signature/>";
+
+ /**
+ * Constructor
+ */
+ public CertInfoVerifyXMLSignatureRequestBuilder() {
+ super();
+ }
+ /**
+ * Builds the <code>&lt;VerifyXMLSignatureRequest&gt;</code> structure.
+ * @return the XML structure
+ * @throws BuildException
+ */
+ public String build() throws BuildException {
+ String resCertInfoRequest = "resources/xmldata/CertInfoVerifyXMLSignatureRequest.xml";
+ String resDsigSignature = "resources/xmldata/CertInfoDsigSignature.xml";
+ String certInfoRequest;
+ try {
+ certInfoRequest = FileUtils.readResource(resCertInfoRequest, "UTF-8");
+ }
+ catch (IOException ex) {
+ throw new BuildException("auth.04", new Object[] {resCertInfoRequest, ex.toString()});
+ }
+ try {
+ String dsigSignature = FileUtils.readResource(resDsigSignature, "UTF-8");
+ certInfoRequest = replaceTag(certInfoRequest, SIGNATURE_TAG, dsigSignature);
+ return certInfoRequest;
+ }
+ catch (IOException ex) {
+ throw new BuildException("auth.04", new Object[] {resDsigSignature, ex.toString()});
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java
new file mode 100644
index 000000000..8693c71a9
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java
@@ -0,0 +1,58 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import java.text.MessageFormat;
+
+import at.gv.egovernment.moa.util.Constants;
+
+/**
+ * Builder for the <code>&lt;CreateXMLSignatureRequest&gt;</code> structure
+ * used for requesting a signature under the authentication block from the
+ * security layer implementation.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class CreateXMLSignatureRequestBuilder implements Constants {
+ /** private static String nl contains the NewLine representation in Java*/
+ private static final String nl = "\n";
+ /**
+ * XML template for the <code>&lt;moa:CreateXMLSignatureRequest&gt;</code> to be built
+ */
+ private static final String CREATE_XML_SIGNATURE_REQUEST =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + nl +
+ "<sl11:CreateXMLSignatureRequest xmlns:dsig=''" + DSIG_NS_URI + "'' xmlns:sl10=''" + SL10_NS_URI + "'' xmlns:sl11=''" + SL11_NS_URI + "''>" + nl +
+ " <sl11:KeyboxIdentifier>SecureSignatureKeypair</sl11:KeyboxIdentifier>" + nl +
+ " <sl11:DataObjectInfo Structure=''detached''>" + nl +
+ " <sl10:DataObject Reference=''''/>" + nl +
+ "{1}" +
+ " </sl11:DataObjectInfo>" + nl +
+ " <sl11:SignatureInfo>" + nl +
+ " <sl11:SignatureEnvironment>" + nl +
+ " <sl10:XMLContent>{0}</sl10:XMLContent>" + nl +
+ " </sl11:SignatureEnvironment>" + nl +
+ " <sl11:SignatureLocation Index=''2''>/saml:Assertion</sl11:SignatureLocation>" + nl +
+ " </sl11:SignatureInfo>" + nl +
+ "</sl11:CreateXMLSignatureRequest>";
+
+ /**
+ * Constructor for CreateXMLSignatureRequestBuilder.
+ */
+ public CreateXMLSignatureRequestBuilder() {
+ super();
+ }
+
+ /**
+ * Builds the <code>&lt;CreateXMLSignatureRequest&gt;</code>.
+ *
+ * @param authBlock String representation of XML authentication block
+ * @return String representation of <code>&lt;CreateXMLSignatureRequest&gt;</code>
+ */
+ public String build(String authBlock, String[] dsigTransformInfos) {
+ String dsigTransformInfosString = "";
+ for (int i = 0; i < dsigTransformInfos.length; i++)
+ dsigTransformInfosString += dsigTransformInfos[i];
+ String request = MessageFormat.format(
+ CREATE_XML_SIGNATURE_REQUEST, new Object[] { authBlock, dsigTransformInfosString });
+ return request;
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/DataURLBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/DataURLBuilder.java
new file mode 100644
index 000000000..575149d9e
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/DataURLBuilder.java
@@ -0,0 +1,55 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
+
+/**
+ * Builds a DataURL parameter meant for the security layer implementation
+ * to respond to.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class DataURLBuilder {
+
+ /**
+ * Constructor for DataURLBuilder.
+ */
+ public DataURLBuilder() {
+ super();
+ }
+
+ /**
+ * Constructs a data URL for <code>VerifyIdentityLink</code> or <code>VerifyAuthenticationBlock</code>,
+ * including the <code>MOASessionID</code> as a parameter.
+ *
+ * @param authBaseURL base URL (context path) of the MOA ID Authentication component,
+ * including a trailing <code>'/'</code>
+ * @param authServletName request part of the data URL
+ * @param sessionID sessionID to be included in the dataURL
+ * @return String
+ */
+ public String buildDataURL(String authBaseURL, String authServletName, String sessionID) {
+ String dataURL = authBaseURL + authServletName;
+ dataURL = addParameter(dataURL, AuthServlet.PARAM_SESSIONID, sessionID);
+ return dataURL;
+ }
+
+ /**
+ * Method addParameter.
+ * @param urlString represents the url
+ * @param paramname is the parameter to be added
+ * @param value is the value of that parameter
+ * @return String
+ */
+ private String addParameter(String urlString, String paramname, String value) {
+ String url = urlString;
+ if (paramname != null) {
+ if (url.indexOf("?") < 0)
+ url += "?";
+ else
+ url += "&";
+ url += paramname + "=" + value;
+ }
+ return url;
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/GetIdentityLinkFormBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/GetIdentityLinkFormBuilder.java
new file mode 100644
index 000000000..8391fdd62
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/GetIdentityLinkFormBuilder.java
@@ -0,0 +1,137 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import at.gv.egovernment.moa.id.BuildException;
+
+/**
+ * Builder for HTML form requesting the security layer implementation
+ * to get the identity link from smartcard by a <code>&lt;InfoboxReadRequest&gt;</code>.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class GetIdentityLinkFormBuilder extends Builder {
+ /** private static String NL contains the NewLine representation in Java*/
+ private static final String nl = "\n";
+ /** special tag in the HTML template to be substituted for the BKU URL */
+ private static final String BKU_TAG = "<BKU>";
+ /** special tag in the HTML template to be substituted for the XML request */
+ private static final String XMLREQUEST_TAG = "<XMLRequest>";
+ /** special tag in the HTML template to be substituted for the data URL */
+ private static final String DATAURL_TAG = "<DataURL>";
+ /** special tag in the HTML template to be substituted for certificate info XML request */
+ private static final String CERTINFO_XMLREQUEST_TAG = "<CertInfoXMLRequest>";
+ /** special tag in the HTML template to be substituted for the certificate info data URL */
+ private static final String CERTINFO_DATAURL_TAG = "<CertInfoDataURL>";
+
+ /** default BKU URL */
+ private static final String DEFAULT_BKU = "http://localhost:3495/http-security-layer-request";
+ /** default HTML template */
+ private static final String DEFAULT_HTML_TEMPLATE =
+ "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">" + nl +
+ "<html>" + nl +
+ "<head>" + nl +
+ "<title>Auslesen der Personenbindung</title>" + nl +
+ "</head>" + nl +
+ "<body>" + nl +
+ "<form name=\"GetIdentityLinkForm\"" + nl +
+ " action=\"" + BKU_TAG + "\"" + nl +
+ " method=\"post\">" + nl +
+ " <input type=\"hidden\" " + nl +
+ " name=\"XMLRequest\"" + nl +
+ " value=\"" + XMLREQUEST_TAG + "\"/>" + nl +
+ " <input type=\"hidden\" " + nl +
+ " name=\"DataURL\"" + nl +
+ " value=\"" + DATAURL_TAG + "\"/>" + nl +
+ " <input type=\"submit\" value=\"Auslesen der Personenbindung\"/>" + nl +
+ "</form>" + nl +
+ "<form name=\"CertificateInfoForm\"" + nl +
+ " action=\"" + BKU_TAG + "\"" + nl +
+ " method=\"post\">" + nl +
+ " <input type=\"hidden\" " + nl +
+ " name=\"XMLRequest\"" + nl +
+ " value=\"" + CERTINFO_XMLREQUEST_TAG + "\"/>" + nl +
+ " <input type=\"hidden\" " + nl +
+ " name=\"DataURL\"" + nl +
+ " value=\"" + CERTINFO_DATAURL_TAG + "\"/>" + nl +
+ " <input type=\"submit\" value=\"Information zu Wurzelzertifikaten\"/>" + nl +
+ "</form>" + nl +
+ "</body>" + nl +
+ "</html>";
+
+ /**
+ * Constructor for GetIdentityLinkFormBuilder.
+ */
+ public GetIdentityLinkFormBuilder() {
+ super();
+ }
+ /**
+ * Builds the HTML form, including XML Request and data URL as parameters.
+ *
+ * @param htmlTemplate template to be used for the HTML form;
+ * may be <code>null</code>, in this case a default layout will be produced
+ * @param xmlRequest XML Request to be sent as a parameter in the form
+ * @param bkuURL URL of the "B&uuml;rgerkartenumgebung" the form will be submitted to;
+ * may be <code>null</code>, in this case the default URL will be used
+ * @param dataURL DataURL to be sent as a parameter in the form
+ */
+ public String build(
+ String htmlTemplate, String bkuURL, String xmlRequest, String dataURL, String certInfoXMLRequest, String certInfoDataURL)
+ throws BuildException {
+
+ String htmlForm = htmlTemplate == null ? DEFAULT_HTML_TEMPLATE : htmlTemplate;
+ String bku = bkuURL == null ? DEFAULT_BKU : bkuURL;
+ htmlForm = replaceTag(htmlForm, BKU_TAG, bku);
+ htmlForm = replaceTag(htmlForm, XMLREQUEST_TAG, encodeParameter(xmlRequest));
+ htmlForm = replaceTag(htmlForm, DATAURL_TAG, dataURL);
+ htmlForm = replaceTag(htmlForm, BKU_TAG, bku);
+ htmlForm = replaceTag(htmlForm, CERTINFO_XMLREQUEST_TAG, encodeParameter(certInfoXMLRequest));
+ htmlForm = replaceTag(htmlForm, CERTINFO_DATAURL_TAG, certInfoDataURL);
+ return htmlForm;
+ }
+ /**
+ * Encodes a string for inclusion as a parameter in the form.
+ * Double quotes are substituted by <code>"&amp;quot;"</code>.
+ * @param s the string to be encoded
+ * @return the string encoded
+ * @throws BuildException on any exception encountered
+ */
+ public static String encodeParameter(String s) throws BuildException {
+ StringReader in = new StringReader(s);
+ StringWriter out = new StringWriter();
+ try {
+ for (int ch = in.read(); ch >= 0; ch = in.read()) {
+ if (ch == '"')
+ out.write("&quot;");
+ else if (ch == '<')
+ out.write("&lt;");
+ else if (ch == '>')
+ out.write("&gt;");
+ else if (ch == 'ä')
+ out.write("&auml;");
+ else if (ch == 'ö')
+ out.write("&ouml;");
+ else if (ch == 'ü')
+ out.write("&uuml;");
+ else if (ch == 'Ä')
+ out.write("&Auml;");
+ else if (ch == 'Ö')
+ out.write("&Ouml;");
+ else if (ch == 'Ü')
+ out.write("&Uuml;");
+ else if (ch == 'ß')
+ out.write("&szlig;");
+ else
+ out.write(ch);
+ }
+ }
+ catch (IOException ex) {
+ throw new BuildException("builder.00", new Object[] {"GetIdentityLinkForm", ex.toString()});
+ }
+ return out.toString();
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/InfoboxReadRequestBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/InfoboxReadRequestBuilder.java
new file mode 100644
index 000000000..d3e100671
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/InfoboxReadRequestBuilder.java
@@ -0,0 +1,39 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import at.gv.egovernment.moa.util.Constants;
+
+/**
+ * Builder for the <code>&lt;InfoboxReadRequest&gt;</code> structure
+ * used for requesting the identity link from the security layer implementation.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class InfoboxReadRequestBuilder implements Constants {
+
+ /**
+ * XML template for the <code>&lt;sl10:InfoboxReadRequest&gt;</code> to be built
+ */
+ String INFOBOX_READ_REQUEST =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" +
+ "<sl10:InfoboxReadRequest xmlns:sl10=\"" + SL10_NS_URI + "\">" +
+ "<sl10:InfoboxIdentifier>IdentityLink</sl10:InfoboxIdentifier>" +
+ "<sl10:BinaryFileParameters ContentIsXMLEntity=\"true\"/>" +
+ "</sl10:InfoboxReadRequest>";
+
+ /**
+ * Constructor for InfoboxReadRequestBuilder.
+ */
+ public InfoboxReadRequestBuilder() {
+ }
+ /**
+ * Builds an <code>&lt;InfoboxReadRequest&gt;</code>.
+ *
+ * @return <code>&lt;InfoboxReadRequest&gt;</code> as String
+ */
+ public String build() {
+ String request = INFOBOX_READ_REQUEST;
+ return request;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/PersonDataBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/PersonDataBuilder.java
new file mode 100644
index 000000000..85ec1cb7f
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/PersonDataBuilder.java
@@ -0,0 +1,58 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import at.gv.egovernment.moa.id.BuildException;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Builder for the <code>lt;pr:Person&gt;</code> element to be inserted
+ * in the authentication data <code>lt;saml:Assertion&gt;</code>.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class PersonDataBuilder {
+
+ /**
+ * Constructor for PersonDataBuilder.
+ */
+ public PersonDataBuilder() {
+ super();
+ }
+ /**
+ * Builds the <code>&lt;pr:Person&gt;</code> element.<br/>
+ * Utilizes the parsed <code>&lt;prPerson&gt;</code> from the identity link
+ * and the information regarding inclusion of <code>"ZMR-Zahl"</code> in the
+ * <code>&lt;pr:Person&gt;</code> data.
+ *
+ * @param identityLink <code>IdentityLink</code> containing the
+ * attribute <code>prPerson</code>
+ * @param provideZMRZahl true if <code>"ZMR-Zahl"</code> is to be included;
+ * false otherwise
+ * @return the <code>&lt;pr:Person&gt;</code> element as a String
+ * @throws BuildException on any error
+ */
+ public String build(IdentityLink identityLink, boolean provideZMRZahl)
+ throws BuildException {
+
+ try {
+ Element prPerson = (Element)identityLink.getPrPerson().cloneNode(true);
+ if (! provideZMRZahl) {
+ Node prIdentification = XPathUtils.selectSingleNode(prPerson, "pr:Identification");
+ prPerson.removeChild(prIdentification);
+ }
+ String xmlString = DOMUtils.serializeNode(prPerson);
+ return xmlString;
+ }
+ catch (Exception ex) {
+ throw new BuildException(
+ "builder.00",
+ new Object[] {"PersonData", ex.toString()},
+ ex);
+ }
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilder.java
new file mode 100644
index 000000000..27e19e830
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/SAMLArtifactBuilder.java
@@ -0,0 +1,60 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+
+import at.gv.egovernment.moa.id.BuildException;
+import at.gv.egovernment.moa.util.Base64Utils;
+
+/**
+ * Builder for the SAML artifact, as defined in the
+ * Browser/Artifact profile of SAML.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class SAMLArtifactBuilder {
+
+ /**
+ * Constructor for SAMLArtifactBuilder.
+ */
+ public SAMLArtifactBuilder() {
+ super();
+ }
+
+ /**
+ * Builds the SAML artifact, encoded BASE64.
+ * <ul>
+ * <li><code>TypeCode</code>: <code>0x0001</code>.</li>
+ * <li><code>SourceID</code>: SHA-1 hash of the authURL</li>
+ * <li><code>AssertionHandle</code>: SHA-1 hash of the <code>MOASessionID</code></li>
+ * </ul>
+ * @param authURL URL auf the MOA-ID Auth component to be used for construction
+ * of <code>SourceID</code>
+ * @param sessionID <code>MOASessionID</code> to be used for construction
+ * of <code>AssertionHandle</code>
+ * @return the 42-byte SAML artifact, encoded BASE64
+ */
+ public String build(String authURL, String sessionID) throws BuildException {
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ byte[] sourceID = md.digest(authURL.getBytes());
+ byte[] assertionHandle = md.digest(sessionID.getBytes());
+ ByteArrayOutputStream out = new ByteArrayOutputStream(42);
+ out.write(0);
+ out.write(1);
+ out.write(sourceID, 0, 20);
+ out.write(assertionHandle, 0, 20);
+ byte[] samlArtifact = out.toByteArray();
+ String samlArtifactBase64 = Base64Utils.encode(samlArtifact);
+ return samlArtifactBase64;
+ }
+ catch (Throwable ex) {
+ throw new BuildException(
+ "builder.00",
+ new Object[] {"SAML Artifact, MOASessionID=" + sessionID, ex.toString()},
+ ex);
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/SAMLResponseBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/SAMLResponseBuilder.java
new file mode 100644
index 000000000..a4fb5579e
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/SAMLResponseBuilder.java
@@ -0,0 +1,100 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import java.text.MessageFormat;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.*;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+
+/**
+ * Builder for the <code>lt;samlp:Response&gt;</code> used for passing
+ * result and status information from the <code>GetAuthenticationData</code>
+ * web service.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class SAMLResponseBuilder implements Constants {
+ /** XML - Template for samlp:Response */
+ private static final String RESPONSE =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" +
+ "<samlp:Response xmlns:samlp=\"" + SAMLP_NS_URI + "\" xmlns:saml=\"" + SAML_NS_URI + "\"" +
+ " ResponseID=\"{0}\" InResponseTo=\"{1}\" MajorVersion=\"1\" MinorVersion=\"0\" IssueInstant=\"{2}\">" +
+ " <samlp:Status>" +
+ " <samlp:StatusCode Value=\"{3}\">" +
+ " {4}" +
+ " </samlp:StatusCode>" +
+ " <samlp:StatusMessage>{5}</samlp:StatusMessage>" +
+ " </samlp:Status>" +
+ " {6}" +
+ "</samlp:Response>";
+ /** XML - Template for samlp:StatusCode */
+ private static final String SUB_STATUS_CODE =
+ "<samlp:StatusCode Value=\"{0}\"></samlp:StatusCode>";
+
+ /**
+ * Constructor for SAMLResponseBuilder.
+ */
+ public SAMLResponseBuilder() {
+ super();
+ }
+ /**
+ * Builds the SAML response.
+ * @param responseID response ID
+ * @param inResponseTo request ID of <code>lt;samlp:Request&gt;</code> responded to
+ * @param issueInstant current timestamp
+ * @param statusCode status code
+ * @param subStatusCode sub-status code refining the status code; may be <code>null</code>
+ * @param statusMessage status message
+ * @param samlAssertion SAML assertion representing authentication data
+ * @return SAML response as a DOM element
+ */
+ public Element build(
+ String responseID,
+ String inResponseTo,
+ String issueInstant,
+ String statusCode,
+ String subStatusCode,
+ String statusMessage,
+ String samlAssertion)
+ throws BuildException {
+
+ try {
+ String xmlSubStatusCode =
+ subStatusCode == null ?
+ "" :
+ MessageFormat.format(SUB_STATUS_CODE, new Object[] {subStatusCode});
+ String xmlResponse = MessageFormat.format(RESPONSE, new Object[] {
+ responseID,
+ inResponseTo,
+ issueInstant,
+ statusCode,
+ xmlSubStatusCode,
+ statusMessage,
+ removeXMLDeclaration(samlAssertion) });
+ Element domResponse = DOMUtils.parseDocument(xmlResponse, true, ALL_SCHEMA_LOCATIONS, null).getDocumentElement();
+ return domResponse;
+ }
+ catch (Throwable ex) {
+ throw new BuildException(
+ "builder.00",
+ new Object[] { "samlp:Response", ex.toString() },
+ ex);
+ }
+ }
+ /**
+ * Removes the XML declaration from an XML expression.
+ * @param xmlString XML expression as String
+ * @return XML expression, XML declaration removed
+ */
+ private String removeXMLDeclaration(String xmlString) {
+ if (xmlString.startsWith("<?xml")) {
+ int firstElement = xmlString.indexOf("<", 1);
+ return xmlString.substring(firstElement);
+ }
+ else return xmlString;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/SelectBKUFormBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/SelectBKUFormBuilder.java
new file mode 100644
index 000000000..363cd65a3
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/SelectBKUFormBuilder.java
@@ -0,0 +1,63 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import at.gv.egovernment.moa.id.BuildException;
+
+/**
+ * Builder for the BKU selection form requesting the user to choose
+ * a BKU from a list.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class SelectBKUFormBuilder extends Builder {
+ /** private static String NL contains the NewLine representation in Java*/
+ private static final String nl = "\n";
+ /** special tag in the HTML template to be substituted for the form action which is
+ * a URL of MOA-ID Auth */
+ private static final String ACTION_TAG = "<StartAuth>";
+ /** special tag in the HTML template to be substituted for the <code>&lt;select;gt;</code> tag
+ * containing the BKU selection options */
+ private static final String SELECT_TAG = "<BKUSelect>";
+ /**
+ * Template for the default html-code to be returned as security-layer-selection to be built
+ */
+ private static final String DEFAULT_HTML_TEMPLATE =
+ "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">" + nl +
+ "<html>" + nl +
+ "<head>" + nl +
+ "<title>Auswahl der B&uuml;rgerkartenumgebung</title>" + nl +
+ "</head>" + nl +
+ "<body>" + nl +
+ "<form name=\"BKUSelectionForm\"" + nl +
+ " action=\"" + ACTION_TAG + "\"" + nl +
+ " method=\"post\">" + nl +
+ SELECT_TAG + nl +
+ " <input type=\"submit\" value=\"B&uuml;rgerkartenumgebung ausw&auml;hlen\"/>" + nl +
+ "</form>" + nl +
+ "</body>" + nl +
+ "</html>";
+
+ /**
+ * Constructor
+ */
+ public SelectBKUFormBuilder() {
+ super();
+ }
+ /**
+ * Method build. Builds the form
+ * @param htmlTemplate to be used
+ * @param startAuthenticationURL the url where the startAuthenticationServlet can be found
+ * @param bkuSelectTag if a special bku should be used
+ * @return String
+ * @throws BuildException on any error
+ */
+ public String build(String htmlTemplate, String startAuthenticationURL, String bkuSelectTag)
+ throws BuildException {
+
+ String htmlForm = htmlTemplate == null ? DEFAULT_HTML_TEMPLATE : htmlTemplate;
+ htmlForm = replaceTag(htmlForm, ACTION_TAG, startAuthenticationURL);
+ htmlForm = replaceTag(htmlForm, SELECT_TAG, bkuSelectTag);
+ return htmlForm;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/VPKBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/VPKBuilder.java
new file mode 100644
index 000000000..c18156a01
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/VPKBuilder.java
@@ -0,0 +1,52 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import java.security.MessageDigest;
+
+import at.gv.egovernment.moa.id.BuildException;
+import at.gv.egovernment.moa.util.Base64Utils;
+
+/**
+ * Builder for the VPK, as defined in
+ * <code>&quot;Ableitung f&uml;r die verfahrensspezifische Personenkennzeichnung&quot;</code>
+ * version <code>1.0.1</code> from <code>&quot;reference.e-government.gv.at&quot;</code>.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class VPKBuilder {
+
+ /**
+ * Builds the VPK from given parameters.
+ * @param identificationValue "ZMR-Zahl"
+ * @param dateOfBirth "Geburtsdatum"
+ * @param target "Verfahrensname"; will be transformed to lower case
+ * @return VPK in a BASE64 encoding
+ * @throws BuildException while building the VPK
+ */
+ public String buildVPK(String identificationValue, String dateOfBirth, String target)
+ throws BuildException {
+
+ if (identificationValue == null || identificationValue.length() == 0
+ || dateOfBirth == null || dateOfBirth.length() == 0
+ || target == null || target.length() == 0)
+ throw new BuildException(
+ "builder.00",
+ new Object[] {"VPK",
+ "Unvollständige Parameterangaben: identificationValue=" + identificationValue +
+ ",dateOfBirth=" + dateOfBirth + ",target=" + target});
+ String basisbegriff = identificationValue + "+" + dateOfBirth + "+" + target.toLowerCase();
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ byte[] hash = md.digest(basisbegriff.getBytes());
+ String hashBase64 = Base64Utils.encode(hash);
+ return hashBase64;
+ }
+ catch (Exception ex) {
+ throw new BuildException(
+ "builder.00",
+ new Object[] {"VPK", ex.toString()},
+ ex);
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/builder/VerifyXMLSignatureRequestBuilder.java b/id.server/src/at/gv/egovernment/moa/id/auth/builder/VerifyXMLSignatureRequestBuilder.java
new file mode 100644
index 000000000..863162fd9
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/builder/VerifyXMLSignatureRequestBuilder.java
@@ -0,0 +1,203 @@
+package at.gv.egovernment.moa.id.auth.builder;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.*;
+import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Builder for the <code>&lt;VerifyXMLSignatureRequestBuilder&gt;</code> structure
+ * used for sending the DSIG-Signature of the Security Layer card for validating to MOA-SP.
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class VerifyXMLSignatureRequestBuilder {
+ /** The MOA-Prefix */
+ private static final String MOA = Constants.MOA_PREFIX + ":";
+ /** the request as string */
+ private String request;
+ /** the request as DOM-Element */
+ private Element reqElem;
+
+ /**
+ * Constructor for VerifyXMLSignatureRequestBuilder.
+ */
+ public VerifyXMLSignatureRequestBuilder() {}
+ /**
+ * Builds a <code>&lt;VerifyXMLSignatureRequest&gt;</code>
+ * from an IdentityLink with a known trustProfileID which
+ * has to exist in MOA-SP
+ * @param idl - The IdentityLink
+ * @param trustProfileID - a preconfigured TrustProfile at MOA-SP
+ * @return Element - The complete request as Dom-Element
+ * @throws ParseException
+ */
+ public Element build(IdentityLink idl, String trustProfileID) throws ParseException
+ { //samlAssertionObject
+ request =
+ "<?xml version='1.0' encoding='UTF-8' ?>"
+ + "<VerifyXMLSignatureRequest xmlns=\"http://reference.e-government.gv.at/namespace/moa/20020822#\" xmlns:xml=\"http://www.w3.org/XML/1998/namespace\" xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\">"
+ + " <VerifySignatureInfo>"
+ + " <VerifySignatureEnvironment>"
+ + " <XMLContent xml:space=\"preserve\"/>"
+ + " </VerifySignatureEnvironment>"
+ + " <VerifySignatureLocation>//dsig:Signature</VerifySignatureLocation>"
+ + " </VerifySignatureInfo>"
+ + " <SignatureManifestCheckParams ReturnReferenceInputData=\"false\">" // True bei CreateXMLSig Überprüfung
+ +" <ReferenceInfo>" + " <VerifyTransformsInfoProfile/>"
+ // Profile ID für create (alle auslesen aus IDCOnfig VerifyAuthBlock)
+ +" </ReferenceInfo>" + " </SignatureManifestCheckParams>"
+
+ // Testweise ReturnReferenceInputData = False
+
+ +" <ReturnHashInputData/>"
+ + " <TrustProfileID>"
+ + trustProfileID
+ + "</TrustProfileID>"
+ + "</VerifyXMLSignatureRequest>";
+
+ try {
+ InputStream s = new ByteArrayInputStream(request.getBytes("UTF-8"));
+ reqElem = DOMUtils.parseXmlValidating(s);
+
+ String CONTENT_XPATH =
+ "//"
+ + MOA
+ + "VerifyXMLSignatureRequest/"
+ + MOA
+ + "VerifySignatureInfo/"
+ + MOA
+ + "VerifySignatureEnvironment/"
+ + MOA
+ + "XMLContent";
+
+ Element insertTo =
+ (Element) XPathUtils.selectSingleNode(reqElem, CONTENT_XPATH);
+ insertTo.appendChild(
+ insertTo.getOwnerDocument().importNode(idl.getSamlAssertion(), true));
+
+ String SIGN_MANI_CHECK_PARAMS_XPATH =
+ "//"
+ + MOA
+ + "VerifyXMLSignatureRequest/"
+ + MOA
+ + "SignatureManifestCheckParams";
+ insertTo =
+ (Element) XPathUtils.selectSingleNode(
+ reqElem,
+ SIGN_MANI_CHECK_PARAMS_XPATH);
+ insertTo.removeChild(
+ (Element) XPathUtils.selectSingleNode(
+ reqElem,
+ SIGN_MANI_CHECK_PARAMS_XPATH + "/" + MOA + "ReferenceInfo"));
+ Element[] dsigTransforms = idl.getDsigReferenceTransforms();
+ for (int i = 0; i < 1; i++) //dsigTransforms.length; i++)
+ {
+ Element refInfo =
+ insertTo.getOwnerDocument().createElementNS(
+ Constants.MOA_NS_URI,
+ "ReferenceInfo");
+ insertTo.appendChild(refInfo);
+ Element verifyTransformsInfoProfile =
+ insertTo.getOwnerDocument().createElementNS(
+ Constants.MOA_NS_URI,
+ "VerifyTransformsInfoProfile");
+ refInfo.appendChild(verifyTransformsInfoProfile);
+ verifyTransformsInfoProfile.appendChild(
+ insertTo.getOwnerDocument().importNode(dsigTransforms[i], true));
+ }
+ }
+ catch (Throwable t) {
+ throw new ParseException( //"VerifyXMLSignatureRequest (IdentityLink)");
+ "builder.00",
+ new Object[] { "VerifyXMLSignatureRequest (IdentityLink)" },
+ t);
+ }
+
+ return reqElem;
+ }
+
+ /**
+ * Builds a <code>&lt;VerifyXMLSignatureRequest&gt;</code>
+ * from an IdentityLink with a known trustProfileID which
+ * has to exist in MOA-SP
+ * @param idl - The IdentityLink
+ * @param trustProfileID - a preconfigured TrustProfile at MOA-SP
+ * @return Element - The complete request as Dom-Element
+ * @throws ParseException
+ */
+ public Element build(
+ CreateXMLSignatureResponse csr,
+ String[] verifyTransformsInfoProfileID,
+ String trustProfileID)
+ throws ParseException { //samlAssertionObject
+ request =
+ "<?xml version='1.0' encoding='UTF-8' ?>"
+ + "<VerifyXMLSignatureRequest xmlns=\"http://reference.e-government.gv.at/namespace/moa/20020822#\" xmlns:xml=\"http://www.w3.org/XML/1998/namespace\" xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\">"
+ + " <VerifySignatureInfo>"
+ + " <VerifySignatureEnvironment>"
+ + " <XMLContent xml:space=\"preserve\"/>"
+ + " </VerifySignatureEnvironment>"
+ + " <VerifySignatureLocation>//dsig:Signature</VerifySignatureLocation>"
+ + " </VerifySignatureInfo>"
+ + " <SignatureManifestCheckParams ReturnReferenceInputData=\"true\">"
+ + " <ReferenceInfo>";
+
+ for (int i = 0; i < verifyTransformsInfoProfileID.length; i++) {
+ request += " <VerifyTransformsInfoProfileID>" +
+ verifyTransformsInfoProfileID[i] +
+ "</VerifyTransformsInfoProfileID>";
+ // Profile ID für create (auslesen aus IDCOnfig VerifyAuthBlock ODER per String übergeben....)
+
+ }
+
+ request += " </ReferenceInfo>"
+ + " </SignatureManifestCheckParams>"
+ // Testweise ReturnReferenceInputData = False
+ +" <ReturnHashInputData/>"
+ + " <TrustProfileID>"
+ + trustProfileID
+ + "</TrustProfileID>"
+ + "</VerifyXMLSignatureRequest>";
+
+ try {
+ // Build a DOM-Tree of the obove String
+ InputStream s = new ByteArrayInputStream(request.getBytes("UTF-8"));
+ reqElem = DOMUtils.parseXmlValidating(s);
+ //Insert the SAML-Assertion-Object
+ String CONTENT_XPATH =
+ "//"
+ + MOA
+ + "VerifyXMLSignatureRequest/"
+ + MOA
+ + "VerifySignatureInfo/"
+ + MOA
+ + "VerifySignatureEnvironment/"
+ + MOA
+ + "XMLContent";
+
+ Element insertTo =
+ (Element) XPathUtils.selectSingleNode(reqElem, CONTENT_XPATH);
+ insertTo.appendChild(
+ insertTo.getOwnerDocument().importNode(csr.getSamlAssertion(), true));
+
+ }
+ catch (Throwable t) {
+ throw new ParseException(
+ "builder.00",
+ new Object[] { "VerifyXMLSignatureRequest" },
+ t);
+ }
+
+ return reqElem;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java b/id.server/src/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java
new file mode 100644
index 000000000..ba4a9e367
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java
@@ -0,0 +1,220 @@
+package at.gv.egovernment.moa.id.auth.data;
+
+import java.util.Date;
+
+
+/**
+ * Session data to be stored between <code>AuthenticationServer</code> API calls.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class AuthenticationSession {
+ /**
+ * session ID
+ */
+ private String sessionID;
+ /**
+ * "Gesch&auml;ftsbereich" the online application belongs to
+ */
+ private String target;
+ /**
+ * public online application URL requested
+ */
+ private String oaURLRequested;
+ /**
+ * public online application URL prefix
+ */
+ private String oaPublicURLPrefix;
+ /**
+ * URL of MOA ID authentication component
+ */
+ private String authURL;
+ /**
+ * HTML template URL
+ */
+ private String templateURL;
+ /**
+ * identity link read from smartcard
+ */
+ private IdentityLink identityLink;
+ /**
+ * authentication block to be signed by the user
+ */
+ private String authBlock;
+ /**
+ * timestamp logging when authentication session has been created
+ */
+ private Date timestampStart;
+ /**
+ * timestamp logging when identity link has been received
+ */
+ private Date timestampIdentityLink;
+
+ /**
+ * Constructor for AuthenticationSession.
+ *
+ * @param id Session ID
+ */
+ public AuthenticationSession(String id) {
+ sessionID = id;
+ setTimestampStart();
+ }
+
+ /**
+ * Returns the identityLink.
+ * @return IdentityLink
+ */
+ public IdentityLink getIdentityLink() {
+ return identityLink;
+ }
+
+ /**
+ * Returns the sessionID.
+ * @return String
+ */
+ public String getSessionID() {
+ return sessionID;
+ }
+
+ /**
+ * Sets the identityLink.
+ * @param identityLink The identityLink to set
+ */
+ public void setIdentityLink(IdentityLink identityLink) {
+ this.identityLink = identityLink;
+ }
+
+ /**
+ * Sets the sessionID.
+ * @param sessionID The sessionID to set
+ */
+ public void setSessionID(String sessionId) {
+ this.sessionID = sessionId;
+ }
+
+ /**
+ * Returns the oaURLRequested.
+ * @return String
+ */
+ public String getOAURLRequested() {
+ return oaURLRequested;
+ }
+
+ /**
+ * Returns the oaURLRequested.
+ * @return String
+ */
+ public String getPublicOAURLPrefix() {
+ return oaPublicURLPrefix;
+ }
+
+ /**
+ * Returns the target.
+ * @return String
+ */
+ public String getTarget() {
+ return target;
+ }
+
+ /**
+ * Sets the oaURLRequested.
+ * @param oaURLRequested The oaURLRequested to set
+ */
+ public void setOAURLRequested(String url) {
+ this.oaURLRequested = url;
+ }
+
+ /**
+ * Sets the oaPublicURLPrefix
+ * @param url The oaPublicURLPrefix to set
+ */
+ public void setPublicOAURLPrefix(String url) {
+ this.oaPublicURLPrefix = url;
+ }
+
+ /**
+ * Sets the target.
+ * @param target The target to set
+ */
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ /**
+ * Returns the authURL.
+ * @return String
+ */
+ public String getAuthURL() {
+ return authURL;
+ }
+
+ /**
+ * Sets the authURL.
+ * @param authURL The authURL to set
+ */
+ public void setAuthURL(String authURL) {
+ this.authURL = authURL;
+ }
+
+ /**
+ * Returns the authBlock.
+ * @return String
+ */
+ public String getAuthBlock() {
+ return authBlock;
+ }
+
+ /**
+ * Sets the authBlock.
+ * @param authBlock The authBlock to set
+ */
+ public void setAuthBlock(String authBlock) {
+ this.authBlock = authBlock;
+ }
+
+ /**
+ * Returns the timestampIdentityLink.
+ * @return Date
+ */
+ public Date getTimestampIdentityLink() {
+ return timestampIdentityLink;
+ }
+
+ /**
+ * Returns the timestampStart.
+ * @return Date
+ */
+ public Date getTimestampStart() {
+ return timestampStart;
+ }
+
+ /**
+ * Sets the current date as timestampIdentityLink.
+ */
+ public void setTimestampIdentityLink() {
+ timestampIdentityLink = new Date();
+ }
+
+ /**
+ * Sets the current date as timestampStart.
+ */
+ public void setTimestampStart() {
+ timestampStart = new Date();
+ }
+
+ /**
+ * @return template URL
+ */
+ public String getTemplateURL() {
+ return templateURL;
+ }
+
+ /**
+ * @param string the template URL
+ */
+ public void setTemplateURL(String string) {
+ templateURL = string;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/data/CreateXMLSignatureResponse.java b/id.server/src/at/gv/egovernment/moa/id/auth/data/CreateXMLSignatureResponse.java
new file mode 100644
index 000000000..81945f644
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/data/CreateXMLSignatureResponse.java
@@ -0,0 +1,71 @@
+package at.gv.egovernment.moa.id.auth.data;
+
+import org.w3c.dom.Element;
+
+/**
+ * This bean saves all information of the CreateXMLSignature-Response:
+ * a {@link SAMLAttribute} array, the SamlAssertion-Element and the
+ * saml NameIdentifier
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ *
+ */
+public class CreateXMLSignatureResponse {
+ /** the samlNameIdentifier */
+private String samlNameIdentifier;
+ /** an array of saml-attributes */
+private SAMLAttribute[] samlAttributes;
+ /**
+ * the original saml:Assertion-Element
+ */
+ private Element samlAssertion;
+/**
+ * Returns the samlAssertion.
+ * @return Element
+ */
+public Element getSamlAssertion() {
+ return samlAssertion;
+}
+
+/**
+ * Returns the samlAttribute.
+ * @return SAMLAttribute[]
+ */
+public SAMLAttribute[] getSamlAttributes() {
+ return samlAttributes;
+}
+
+/**
+ * Returns the samlNameIdentifier.
+ * @return String
+ */
+public String getSamlNameIdentifier() {
+ return samlNameIdentifier;
+}
+
+/**
+ * Sets the samlAssertion.
+ * @param samlAssertion The samlAssertion to set
+ */
+public void setSamlAssertion(Element samlAssertion) {
+ this.samlAssertion = samlAssertion;
+}
+
+/**
+ * Sets the samlAttribute.
+ * @param samlAttribute The samlAttribute to set
+ */
+public void setSamlAttributes(SAMLAttribute[] samlAttributes) {
+ this.samlAttributes = samlAttributes;
+}
+
+/**
+ * Sets the samlNameIdentifier.
+ * @param samlNameIdentifier The samlNameIdentifier to set
+ */
+public void setSamlNameIdentifier(String samlNameIdentifier) {
+ this.samlNameIdentifier = samlNameIdentifier;
+}
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/data/IdentityLink.java b/id.server/src/at/gv/egovernment/moa/id/auth/data/IdentityLink.java
new file mode 100644
index 000000000..e2ad2625a
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/data/IdentityLink.java
@@ -0,0 +1,189 @@
+package at.gv.egovernment.moa.id.auth.data;
+
+import java.security.PublicKey;
+
+import org.w3c.dom.Element;
+
+
+/**
+ * Data contained in an identity link issued by BMI, relevant to the MOA ID component.
+ * <br><code>"IdentityLink"</code> is the translation of <code>"Personenbindung"</code>.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class IdentityLink {
+ /**
+ * <code>"identificationValue"</code> is the translation of <code>"ZMR-Zahl"</code>.
+ */
+ private String identificationValue;
+ /**
+ * first name
+ */
+ private String givenName;
+ /**
+ * family name
+ */
+ private String familyName;
+ /**
+ * date of birth
+ */
+ private String dateOfBirth;
+ /**
+ * the original saml:Assertion-Element
+ */
+ private Element samlAssertion;
+ /**
+ * Element /saml:Assertion/saml:AttributeStatement/saml:Subject/saml:SubjectConfirmation/saml:SubjectConfirmationData/pr:Person
+ */
+ private Element prPerson;
+ /**
+ * we need for each dsig:Reference Element all
+ * transformation elements
+ */
+ private Element[] dsigReferenceTransforms;
+
+
+ /**
+ * we need all public keys stored in
+ * the identity link
+ */
+ private PublicKey[] publicKey;
+
+ /**
+ * Constructor for IdentityLink
+ */
+ public IdentityLink() {
+ }
+
+ /**
+ * Returns the dateOfBirth.
+ * @return Calendar
+ */
+ public String getDateOfBirth() {
+ return dateOfBirth;
+ }
+
+ /**
+ * Returns the familyName.
+ * @return String
+ */
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ /**
+ * Returns the givenName.
+ * @return String
+ */
+ public String getGivenName() {
+ return givenName;
+ }
+
+ /**
+ * Returns the identificationValue.
+ * <code>"identificationValue"</code> is the translation of <code>"ZMR-Zahl"</code>.
+ * @return String
+ */
+ public String getIdentificationValue() {
+ return identificationValue;
+ }
+
+ /**
+ * Sets the dateOfBirth.
+ * @param dateOfBirth The dateOfBirth to set
+ */
+ public void setDateOfBirth(String dateOfBirth) {
+ this.dateOfBirth = dateOfBirth;
+ }
+
+ /**
+ * Sets the familyName.
+ * @param familyName The familyName to set
+ */
+ public void setFamilyName(String familyName) {
+ this.familyName = familyName;
+ }
+
+ /**
+ * Sets the givenName.
+ * @param givenName The givenName to set
+ */
+ public void setGivenName(String givenName) {
+ this.givenName = givenName;
+ }
+
+ /**
+ * Sets the identificationValue.
+ * <code>"identificationValue"</code> is the translation of <code>"ZMR-Zahl"</code>.
+ * @param identificationValue The identificationValue to set
+ */
+ public void setIdentificationValue(String identificationValue) {
+ this.identificationValue = identificationValue;
+ }
+
+ /**
+ * Returns the samlAssertion.
+ * @return Element
+ */
+ public Element getSamlAssertion() {
+ return samlAssertion;
+ }
+
+ /**
+ * Sets the samlAssertion.
+ * @param samlAssertion The samlAssertion to set
+ */
+ public void setSamlAssertion(Element samlAssertion) {
+ this.samlAssertion = samlAssertion;
+ }
+
+ /**
+ * Returns the dsigReferenceTransforms.
+ * @return Element[]
+ */
+ public Element[] getDsigReferenceTransforms() {
+ return dsigReferenceTransforms;
+ }
+
+ /**
+ * Sets the dsigReferenceTransforms.
+ * @param dsigReferenceTransforms The dsigReferenceTransforms to set
+ */
+ public void setDsigReferenceTransforms(Element[] dsigReferenceTransforms) {
+ this.dsigReferenceTransforms = dsigReferenceTransforms;
+ }
+
+ /**
+ * Returns the publicKey.
+ * @return PublicKey[]
+ */
+ public PublicKey[] getPublicKey() {
+ return publicKey;
+ }
+
+ /**
+ * Sets the publicKey.
+ * @param publicKey The publicKey to set
+ */
+ public void setPublicKey(PublicKey[] publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ /**
+ * Returns the prPerson.
+ * @return Element
+ */
+ public Element getPrPerson() {
+ return prPerson;
+ }
+
+ /**
+ * Sets the prPerson.
+ * @param prPerson The prPerson to set
+ */
+ public void setPrPerson(Element prPerson) {
+ this.prPerson = prPerson;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/data/SAMLAttribute.java b/id.server/src/at/gv/egovernment/moa/id/auth/data/SAMLAttribute.java
new file mode 100644
index 000000000..c787b2a81
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/data/SAMLAttribute.java
@@ -0,0 +1,78 @@
+package at.gv.egovernment.moa.id.auth.data;
+
+/**
+ * This bean saves all data of a single SAMLAttribute:
+ * the name, value and namespace
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ *
+ */
+public class SAMLAttribute {
+/** the name to be stored */
+private String name;
+/** the namespace to be stored */
+private String namespace;
+/** the value to be stored */
+private String value;
+
+ /**
+ * Constructor for SAMLAttribute.
+ */
+ public SAMLAttribute(String name, String namespace, String value) {
+
+ this.name = name;
+ this.namespace = namespace;
+ this.value = value;
+
+ }
+
+/**
+ * Returns the name.
+ * @return String
+ */
+public String getName() {
+ return name;
+}
+
+/**
+ * Returns the namespace.
+ * @return String
+ */
+public String getNamespace() {
+ return namespace;
+}
+
+/**
+ * Returns the value.
+ * @return String
+ */
+public String getValue() {
+ return value;
+}
+
+/**
+ * Sets the name.
+ * @param name The name to set
+ */
+public void setName(String name) {
+ this.name = name;
+}
+
+/**
+ * Sets the namespace.
+ * @param namespace The namespace to set
+ */
+public void setNamespace(String namespace) {
+ this.namespace = namespace;
+}
+
+/**
+ * Sets the value.
+ * @param value The value to set
+ */
+public void setValue(String value) {
+ this.value = value;
+}
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/data/VerifyXMLSignatureResponse.java b/id.server/src/at/gv/egovernment/moa/id/auth/data/VerifyXMLSignatureResponse.java
new file mode 100644
index 000000000..8233d1478
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/data/VerifyXMLSignatureResponse.java
@@ -0,0 +1,177 @@
+package at.gv.egovernment.moa.id.auth.data;
+
+import iaik.x509.X509Certificate;
+
+/**
+ * This bean saves all information of the MOA-SP-Answer
+ * after the verification of any signature
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ *
+ */
+public class VerifyXMLSignatureResponse {
+ /** The xmlDsigSubjectName to be stored */
+ private String xmlDsigSubjectName;
+ /** The signatureCheckCode to be stored */
+ private int signatureCheckCode;
+ /** The xmlDSIGManifestCheckCode to be stored */
+ private int xmlDSIGManifestCheckCode;
+ /** The xmlDSIGManigest to be stored */
+ private boolean xmlDSIGManigest;
+ /** The certificateCheckCode to be stored */
+ private int certificateCheckCode;
+ /** The publicAuthority to be stored */
+ private boolean publicAuthority;
+ /** The publicAuthorityCode to be stored */
+ private String publicAuthorityCode;
+ /** The qualifiedCertificate to be stored */
+ private boolean qualifiedCertificate;
+ /** The x509certificate to be stored */
+ private X509Certificate x509certificate;
+
+ /**
+ * Returns the certificateCheckCode.
+ * @return int
+ */
+ public int getCertificateCheckCode() {
+ return certificateCheckCode;
+ }
+
+ /**
+ * Returns the signatureCheckCode.
+ * @return int
+ */
+ public int getSignatureCheckCode() {
+ return signatureCheckCode;
+ }
+
+ /**
+ * Returns the xmlDSIGManifestCheckCode.
+ * @return int
+ */
+ public int getXmlDSIGManifestCheckCode() {
+ return xmlDSIGManifestCheckCode;
+ }
+
+ /**
+ * Returns the xmlDsigSubjectName.
+ * @return String
+ */
+ public String getXmlDsigSubjectName() {
+ return xmlDsigSubjectName;
+ }
+
+ /**
+ * Sets the certificateCheckCode.
+ * @param certificateCheckCode The certificateCheckCode to set
+ */
+ public void setCertificateCheckCode(int certificateCheckCode) {
+ this.certificateCheckCode = certificateCheckCode;
+ }
+
+ /**
+ * Sets the signatureCheckCode.
+ * @param signatureCheckCode The signatureCheckCode to set
+ */
+ public void setSignatureCheckCode(int signatureCheckCode) {
+ this.signatureCheckCode = signatureCheckCode;
+ }
+
+ /**
+ * Sets the xmlDSIGManifestCheckCode.
+ * @param xmlDSIGManifestCheckCode The xmlDSIGManifestCheckCode to set
+ */
+ public void setXmlDSIGManifestCheckCode(int xmlDSIGManifestCheckCode) {
+ this.xmlDSIGManifestCheckCode = xmlDSIGManifestCheckCode;
+ }
+
+ /**
+ * Sets the xmlDsigSubjectName.
+ * @param xmlDsigSubjectName The xmlDsigSubjectName to set
+ */
+ public void setXmlDsigSubjectName(String xmlDsigSubjectName) {
+ this.xmlDsigSubjectName = xmlDsigSubjectName;
+ }
+
+ /**
+ * Returns the publicAuthorityCode.
+ * @return int
+ */
+ public String getPublicAuthorityCode() {
+ return publicAuthorityCode;
+ }
+
+ /**
+ * Sets the publicAuthorityCode.
+ * @param publicAuthorityCode The publicAuthorityCode to set
+ */
+ public void setPublicAuthorityCode(String publicAuthorityCode) {
+ this.publicAuthorityCode = publicAuthorityCode;
+ }
+
+ /**
+ * Returns the qualifiedCertificate.
+ * @return boolean
+ */
+ public boolean isQualifiedCertificate() {
+ return qualifiedCertificate;
+ }
+
+ /**
+ * Returns the x509certificate.
+ * @return X509Certificate
+ */
+ public X509Certificate getX509certificate() {
+ return x509certificate;
+ }
+
+ /**
+ * Sets the qualifiedCertificate.
+ * @param qualifiedCertificate The qualifiedCertificate to set
+ */
+ public void setQualifiedCertificate(boolean qualifiedCertificate) {
+ this.qualifiedCertificate = qualifiedCertificate;
+ }
+
+ /**
+ * Sets the x509certificate.
+ * @param x509certificate The x509certificate to set
+ */
+ public void setX509certificate(X509Certificate x509certificate) {
+ this.x509certificate = x509certificate;
+ }
+
+ /**
+ * Returns the xmlDSIGManigest.
+ * @return boolean
+ */
+ public boolean isXmlDSIGManigest() {
+ return xmlDSIGManigest;
+ }
+
+ /**
+ * Sets the xmlDSIGManigest.
+ * @param xmlDSIGManigest The xmlDSIGManigest to set
+ */
+ public void setXmlDSIGManigest(boolean xmlDSIGManigest) {
+ this.xmlDSIGManigest = xmlDSIGManigest;
+ }
+
+ /**
+ * Returns the publicAuthority.
+ * @return boolean
+ */
+ public boolean isPublicAuthority() {
+ return publicAuthority;
+ }
+
+ /**
+ * Sets the publicAuthority.
+ * @param publicAuthority The publicAuthority to set
+ */
+ public void setPublicAuthority(boolean publicAuthority) {
+ this.publicAuthority = publicAuthority;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java b/id.server/src/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java
new file mode 100644
index 000000000..8faa69260
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/invoke/SignatureVerificationInvoker.java
@@ -0,0 +1,91 @@
+package at.gv.egovernment.moa.id.auth.invoke;
+
+import java.util.Vector;
+
+import javax.xml.namespace.QName;
+import javax.xml.rpc.Call;
+import javax.xml.rpc.Service;
+import javax.xml.rpc.ServiceFactory;
+
+import org.apache.axis.message.SOAPBodyElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.ServiceException;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.spss.api.SignatureVerificationService;
+import at.gv.egovernment.moa.spss.api.xmlbind.VerifyXMLSignatureRequestParser;
+import at.gv.egovernment.moa.spss.api.xmlbind.VerifyXMLSignatureResponseBuilder;
+import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest;
+import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse;
+
+/**
+ * Invoker of the <code>SignatureVerification</code> web service of MOA-SPSS.<br>
+ * Either invokes the web service, or calls the corresponding API, depending on configuration data.
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class SignatureVerificationInvoker {
+ /** This QName Object identifies the SignatureVerification endpoint of the web service */
+ private static final QName SERVICE_QNAME = new QName("SignatureVerification");
+
+ /**
+ * Method verifyXMLSignature.
+ * @param request to be sent
+ * @return Element with the answer
+ * @throws ServiceException if an error occurs
+ */
+ public Element verifyXMLSignature(Element request) throws ServiceException {
+ return doCall(SERVICE_QNAME, request);
+ }
+
+ /**
+ * Method doCall.
+ * @param serviceName the name of the service
+ * @param request the request to be sent
+ * @return Element the answer
+ * @throws ServiceException if an error occurs
+ */
+ protected Element doCall(QName serviceName, Element request) throws ServiceException {
+ ConnectionParameter authConnParam = null;
+ try {
+ Service service = ServiceFactory.newInstance().createService(serviceName);
+ Call call = service.createCall();
+ SOAPBodyElement body = new SOAPBodyElement(request);
+ SOAPBodyElement[] params = new SOAPBodyElement[] { body };
+ Vector responses;
+ SOAPBodyElement response;
+
+ String endPoint;
+ AuthConfigurationProvider authConfigProvider = AuthConfigurationProvider.getInstance();
+ authConnParam = authConfigProvider.getMoaSpConnectionParameter();
+
+ //If the ConnectionParameter do NOT exist, we try to get the api to work....
+ if (authConnParam != null) {
+ endPoint = authConnParam.getUrl();
+ call.setTargetEndpointAddress(endPoint);
+ responses = (Vector) call.invoke(serviceName, params);
+ response = (SOAPBodyElement) responses.get(0);
+ return response.getAsDOM();
+ }
+ else {
+ SignatureVerificationService svs = SignatureVerificationService.getInstance();
+ VerifyXMLSignatureRequest vsrequest = new VerifyXMLSignatureRequestParser().parse(request);
+ VerifyXMLSignatureResponse vsresponse = svs.verifyXMLSignature(vsrequest);
+
+ Document result = new VerifyXMLSignatureResponseBuilder().build(vsresponse);
+ Logger.setHierarchy("moa.id.auth");
+ return result.getDocumentElement();
+ }
+ }
+ catch (Exception ex) {
+ if (authConnParam != null)
+ throw new ServiceException("service.00", new Object[] { ex.toString()}, ex);
+ else
+ throw new ServiceException("service.03", new Object[] { ex.toString()}, ex);
+ }
+ }
+} \ No newline at end of file
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/parser/CreateXMLSignatureResponseParser.java b/id.server/src/at/gv/egovernment/moa/id/auth/parser/CreateXMLSignatureResponseParser.java
new file mode 100644
index 000000000..1079a48de
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/parser/CreateXMLSignatureResponseParser.java
@@ -0,0 +1,140 @@
+package at.gv.egovernment.moa.id.auth.parser;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.traversal.NodeIterator;
+
+import at.gv.egovernment.moa.id.*;
+import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse;
+import at.gv.egovernment.moa.id.auth.data.SAMLAttribute;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Parses an <code>&lt;InfoboxReadResponse&gt;</code> returned from
+ * the security layer
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+
+public class CreateXMLSignatureResponseParser {
+ //
+ // XPath namespace prefix shortcuts
+ //
+ /** Xpath prefix for reaching SecurityLayer 1.0 Namespaces */
+ private static final String SL10 = Constants.SL10_PREFIX + ":";
+ /** Xpath prefix for reaching SecurityLayer 1.1 Namespaces */
+ private static final String SL11 = Constants.SL11_PREFIX + ":";
+ /** Xpath prefix for reaching SAML Namespaces */
+ private static final String SAML = Constants.SAML_PREFIX + ":";
+ /** Xpath prefix for reaching XML-DSIG Namespaces */
+ private static final String DSIG = Constants.DSIG_PREFIX + ":";
+ /** Xpath expression to the root element */
+ private static final String ROOT = "/" + SL11 + "CreateXMLSignatureResponse/";
+ /** Xpath expression to the SAML:Assertion element */
+ private static final String SAML_ASSERTION_XPATH = ROOT + SAML + "Assertion";
+ /** Xpath expression to the SAML:NameIdentifier element */
+ private static final String SAML_SUBJECT_NAME_IDENTIFIER_XPATH = SAML_ASSERTION_XPATH + "/" + SAML + "AttributeStatement/" + SAML + "Subject/" + SAML + "NameIdentifier";
+ /** Xpath expression to the AttributeStatement element */
+ private static final String SAML_ATTRIBUTE_XPATH = SAML_ASSERTION_XPATH + "/" + SAML + "AttributeStatement/" + SAML + "Attribute";
+ /** Xpath expression to the AttributeValue element */
+ private static final String SAML_ATTRIBUTE_VALUE_XPATH = SAML + "AttributeValue";
+
+ /** This is the root element of the XML-Document provided by the Security Layer Card */
+ private Element sigResponse;
+
+ /**
+ * Constructor for CreateXMLSignatureResponseParser.
+ * A DOM-representation of the incoming String will be created
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as String
+ * @throws AuthenticationException if any authentication error occurs
+ * @throws ParseException if an element cannot be parsed
+ */
+ public CreateXMLSignatureResponseParser(String xmlResponse) throws AuthenticationException, ParseException {
+ ErrorResponseParser erp = new ErrorResponseParser(xmlResponse);
+ if (erp.getErrorCode() != null) {
+ throw new AuthenticationException("auth.08", new Object[] { erp.getErrorCode(), erp.getErrorInfo()});
+ }
+
+ try {
+
+ InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8"));
+ sigResponse = DOMUtils.parseXmlValidating(s);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString()}, t);
+ }
+ }
+
+ /**
+ * Constructor for CreateXMLSignatureResponseParser.
+ * A DOM-representation of the incoming Inputstream will be created
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as InputStream
+ * @throws AuthenticationException if any Authentication error occurs
+ * @throws ParseException if an element cannot be parsed
+ */
+ public CreateXMLSignatureResponseParser(InputStream is) throws AuthenticationException, ParseException {
+
+ ErrorResponseParser erp = new ErrorResponseParser(is);
+ if (erp.getErrorCode() != null) {
+ throw new AuthenticationException("auth.08", new Object[] { erp.getErrorCode(), erp.getErrorInfo()});
+ }
+
+ try {
+
+ sigResponse = DOMUtils.parseXmlValidating(is);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString()}, t);
+ }
+ }
+
+ /**
+ * Constructor for CreateXMLSignatureResponseParser.
+ * The incoming Element will be used for further operations
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as InputStream
+ */
+ public CreateXMLSignatureResponseParser(Element xmlResponse) {
+ sigResponse = xmlResponse;
+
+ }
+
+ /**
+ * Parses the identity link from <code>&lt;InfoboxReadResponse&gt;</code>
+ * @return Identity link
+ * @throws ParseException
+ */
+
+ public CreateXMLSignatureResponse parseResponse() throws ParseException {
+ CreateXMLSignatureResponse cResp;
+ try {
+
+ cResp = new CreateXMLSignatureResponse();
+ cResp.setSamlNameIdentifier(XPathUtils.getElementValue(sigResponse, SAML_SUBJECT_NAME_IDENTIFIER_XPATH, null));
+ cResp.setSamlAssertion((Element) XPathUtils.selectSingleNode(sigResponse, SAML_ASSERTION_XPATH));
+ NodeIterator attrIter = XPathUtils.selectNodeIterator(sigResponse, SAML_ATTRIBUTE_XPATH);
+ Element samlAttr;
+ List samlAttributes = new ArrayList();
+ while ((samlAttr = (Element) attrIter.nextNode()) != null) {
+ String attrName = XPathUtils.getAttributeValue(samlAttr, "@AttributeName", "");
+ String attrNamespace = XPathUtils.getAttributeValue(samlAttr, "@AttributeNamespace", "");
+ String attrValue = XPathUtils.getElementValue(samlAttr, SAML_ATTRIBUTE_VALUE_XPATH, "");
+ samlAttributes.add(new SAMLAttribute(attrName, attrNamespace, attrValue));
+ }
+ SAMLAttribute[] result = new SAMLAttribute[samlAttributes.size()];
+ samlAttributes.toArray(result);
+ cResp.setSamlAttributes(result);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString()}, t);
+ }
+ return cResp;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/parser/ECDSAKeyValueConverter.java b/id.server/src/at/gv/egovernment/moa/id/auth/parser/ECDSAKeyValueConverter.java
new file mode 100644
index 000000000..c28cfac76
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/parser/ECDSAKeyValueConverter.java
@@ -0,0 +1,350 @@
+package at.gv.egovernment.moa.id.auth.parser;
+
+import iaik.security.ecc.ecdsa.ECDSAParameter;
+import iaik.security.ecc.ecdsa.ECPublicKey;
+import iaik.security.ecc.math.ecgroup.ECGroupFactory;
+import iaik.security.ecc.math.ecgroup.ECPoint;
+import iaik.security.ecc.math.ecgroup.EllipticCurve;
+import iaik.security.ecc.math.ecgroup.ProjectiveCoordinate;
+import iaik.security.ecc.math.field.Field;
+import iaik.security.ecc.math.field.FieldElement;
+import iaik.security.ecc.math.field.FieldFactory;
+import iaik.security.ecc.math.field.Value;
+import iaik.security.ecc.parameter.ECCParameterFactory;
+import iaik.security.ecc.spec.ECCParameterSpec;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Vector;
+import java.net.URL;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import at.gv.egovernment.moa.util.Constants;
+
+/**
+ * @author Stefan Knirsch
+ * @version $Id$
+ *
+ */
+public class ECDSAKeyValueConverter
+{
+ /** Namespaces */
+ public static final String NAMESPACE_XSI = "http://www.w3.org/2001/XMLSchema-instance";
+
+ /**
+ * Method element2ECDSAPublicKey.
+ * @param keyValueElem a DomElement containing an ECDSA Public Key
+ * @return PublicKey a java.security.publicKey - object
+ * @throws Exception on any error
+ */
+
+ public static PublicKey element2ECDSAPublicKey(Element keyValueElem) throws Exception
+ {
+ String ecdsaNS = Constants.ECDSA_NS_URI;
+ // Domain parameters
+ Element domainParams = getChildElement(keyValueElem, ecdsaNS, "DomainParameters", 1);
+ if (domainParams == null) throw new Exception("Domain parameters must not be implicit.");
+ Element namedCurve = getChildElement(domainParams, ecdsaNS, "NamedCurve", 1);
+ ECCParameterSpec eccParameterSpec;
+ if (namedCurve != null)
+ {
+ URL curveNameURN = new URL(namedCurve.getAttributeNS(null, "URN"));
+ ECCParameterFactory eccParamFactory = ECCParameterFactory.getInstance();
+ eccParameterSpec = eccParamFactory.getParameterByOID(curveNameURN.getPath().substring(4));
+ }
+ else
+ {
+ Element excplicitParams = getChildElement(domainParams, ecdsaNS, "ExplicitParams", 1);
+ Element fieldParams = getChildElement(excplicitParams, ecdsaNS, "FieldParams", 1);
+ Element curveParams = getChildElement(excplicitParams, ecdsaNS, "CurveParams", 1);
+ Element basePointParams = getChildElement(excplicitParams, ecdsaNS, "BasePointParams", 1);
+
+ // Field parameters
+ String fieldParamsTypeStr = fieldParams.getAttributeNS(NAMESPACE_XSI, "type");
+ String ecdsaNSPrefix = getECDSANSPrefix(fieldParams);
+ BigInteger p = null;
+ int fieldParamsType = 0;
+ final int FIELD_TYPE_PRIME = 1;
+ final int FIELD_TYPE_TNB = 2;
+ final int FIELD_TYPE_PNB = 3;
+ int m = -1, k = -1, k1 = -1, k2 = -1, k3 = -1;
+ if (fieldParamsTypeStr.equals(ecdsaNSPrefix + ":PrimeFieldParamsType"))
+ {
+ fieldParamsType = FIELD_TYPE_PRIME;
+ String pStr = getChildElementText(fieldParams, ecdsaNS, "P", 1);
+ p = new BigInteger(pStr, 10);
+ }
+ else if (fieldParamsTypeStr.equals(ecdsaNSPrefix + ":TnBFieldParamsType"))
+ {
+ fieldParamsType = FIELD_TYPE_TNB;
+ String mStr = getChildElementText(fieldParams, ecdsaNS, "M", 1);
+ m = Integer.parseInt(mStr);
+ String kStr = getChildElementText(fieldParams, ecdsaNS, "K", 1);
+ k = Integer.parseInt(kStr);
+ }
+ else if (fieldParamsTypeStr.equals(ecdsaNSPrefix + ":PnBFieldParamsType"))
+ {
+ fieldParamsType = FIELD_TYPE_PNB;
+ String mStr = getChildElementText(fieldParams, ecdsaNS, "M", 1);
+ m = Integer.parseInt(mStr);
+ String k1Str = getChildElementText(fieldParams, ecdsaNS, "K1", 1);
+ k1 = Integer.parseInt(k1Str);
+ String k2Str = getChildElementText(fieldParams, ecdsaNS, "K2", 1);
+ k2 = Integer.parseInt(k2Str);
+ String k3Str = getChildElementText(fieldParams, ecdsaNS, "K3", 1);
+ k3 = Integer.parseInt(k3Str);
+ }
+ else throw new Exception("Unknown field parameters.");
+
+ // Curve parameters
+ Element aElem = getChildElement(curveParams, ecdsaNS, "A", 1);
+ String aStr = aElem.getAttributeNS(null, "Value");
+ Element bElem = getChildElement(curveParams, ecdsaNS, "B", 1);
+ String bStr = bElem.getAttributeNS(null, "Value");
+ String seedStr = getChildElementText(curveParams, ecdsaNS, "Seed", 1);
+ BigInteger seed = (seedStr != null) ? new BigInteger(seedStr, 10) : null;
+
+ // Base point parameters
+ Element basePoint = getChildElement(basePointParams, ecdsaNS, "BasePoint", 1);
+ Element basePointXElem = getChildElement(basePoint, ecdsaNS, "X", 1);
+ String basePointXStr = basePointXElem.getAttributeNS(null, "Value");
+ Element basePointYElem = getChildElement(basePoint, ecdsaNS, "Y", 1);
+ String basePointYStr = basePointYElem.getAttributeNS(null, "Value");
+ String orderStr = getChildElementText(basePointParams, ecdsaNS, "Order", 1);
+ BigInteger order = new BigInteger(orderStr, 10);
+ String cofactorStr = getChildElementText(basePointParams, ecdsaNS, "Cofactor", 1);
+ BigInteger cofactor = (cofactorStr != null) ? new BigInteger(cofactorStr, 10) : null;
+
+ if (fieldParamsType == FIELD_TYPE_PRIME)
+ {
+ BigInteger a = new BigInteger(aStr, 10);
+ BigInteger b = new BigInteger(bStr, 10);
+ BigInteger basePointX = new BigInteger(basePointXStr, 10);
+ BigInteger basePointY = new BigInteger(basePointYStr, 10);
+ eccParameterSpec = new ECCParameterSpec(p, cofactor, order, seed, null, a, b, basePointX,
+ basePointY, null);
+ }
+ else
+ {
+ int[] irreducible = new int[m/32 + ((m % 32 != 0) ? 1 : 0)];
+ if (fieldParamsType == FIELD_TYPE_TNB)
+ {
+ irreducible[m/32] = 1 << m % 32;
+ irreducible[k/32] += 1 << k % 32;
+ irreducible[0] += 1;
+ }
+ else
+ {
+ irreducible[m/32] = 1 << m % 32;
+ irreducible[k3/32] += 1 << k3 % 32;
+ irreducible[k2/32] += 1 << k2 % 32;
+ irreducible[k1/32] += 1 << k1 % 32;
+ irreducible[0] += 1;
+ }
+ eccParameterSpec = new ECCParameterSpec(irreducible, cofactor, order, octetString2IntArray(aStr),
+ octetString2IntArray(bStr), octetString2IntArray(basePointXStr),
+ octetString2IntArray(basePointYStr), null);
+ }
+ }
+
+ // Public key
+ Element publicKeyElem = getChildElement(keyValueElem, ecdsaNS, "PublicKey", 1);
+ Element publicKeyXElem = getChildElement(publicKeyElem, ecdsaNS, "X", 1);
+ String publicKeyXStr = publicKeyXElem.getAttributeNS(null, "Value");
+ Element publicKeyYElem = getChildElement(publicKeyElem, ecdsaNS, "Y", 1);
+ String publicKeyYStr = publicKeyYElem.getAttributeNS(null, "Value");
+
+ ECDSAParameter ecdsaParams = new ECDSAParameter(eccParameterSpec, false);
+ ECGroupFactory ecGroupFactory = ECGroupFactory.getInstance();
+ EllipticCurve eCurve = ecGroupFactory.getCurveWithProjective(eccParameterSpec.getA(),
+ eccParameterSpec.getB(), eccParameterSpec.getR());
+ Field field = eCurve.getField();
+
+ // Detect type of public key field elements
+ String elementType = publicKeyXElem.getAttributeNS(NAMESPACE_XSI, "type");
+ String elementTypeLocalName = elementType.substring(elementType.indexOf(':') + 1);
+ int FIELD_TYPE_PRIME = 1, FIELD_TYPE_CHAR_TWO = 2;
+ int fieldElemType = ("PrimeFieldElemType".equals(elementTypeLocalName))
+ ? FIELD_TYPE_PRIME
+ : FIELD_TYPE_CHAR_TWO;
+
+ FieldElement publicKeyPointX, publicKeyPointY;
+ if (fieldElemType == FIELD_TYPE_PRIME)
+ {
+ Value xValue = FieldFactory.getInstance().getPrimeFieldValue(new BigInteger(publicKeyXStr, 10));
+ publicKeyPointX = field.newElement(xValue);
+ Value yValue = FieldFactory.getInstance().getPrimeFieldValue(new BigInteger(publicKeyYStr, 10));
+ publicKeyPointY = field.newElement(yValue);
+ }
+ else
+ {
+ publicKeyPointX = field.newElement(octetString2ByteArray(publicKeyXStr));
+ publicKeyPointY = field.newElement(octetString2ByteArray(publicKeyYStr));
+ }
+ ProjectiveCoordinate publicKeyPointCoordinate = new ProjectiveCoordinate(publicKeyPointX,
+ publicKeyPointY, field.getONEelement());
+ ECPoint publicKeyPoint = eCurve.newPoint(publicKeyPointCoordinate);
+ ECPublicKey publicKey = new ECPublicKey(ecdsaParams, publicKeyPoint);
+
+ return publicKey;
+ }
+
+ /**
+ * Method getECDSANSPrefix.
+ * @param element to get the prefix
+ * @return String the prefix
+ */
+ private static String getECDSANSPrefix(Element element)
+ {
+ // FIXXME: Review this function (GK, 11.06.2002) - should return a list of strings, since more than
+ // one NS prefix can be bound to the ECDSA namespace
+
+ HashMap inScopeNSAttrs = getInScopeNSAttrs(element);
+ Iterator inScopeNSAttrsIt = inScopeNSAttrs.keySet().iterator();
+ while (inScopeNSAttrsIt.hasNext())
+ {
+ Attr currentAttr = (Attr)inScopeNSAttrs.get(inScopeNSAttrsIt.next());
+ if (Constants.ECDSA_NS_URI.equals(currentAttr.getValue()))
+ {
+ return ("xmlns".equals(currentAttr.getNodeName())) ? "" : currentAttr.getNodeName().substring(6);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Method octetString2IntArray.
+ * Converts an octet string representation into an int array as needed for the IAIK ECC library
+ * @param octetString rightmost byte is least significant byte
+ * @return int[] rightmost byte is LEAST significant byte
+ */
+ private static int[] octetString2IntArray(String octetString)
+ {
+ int byteCount = octetString.length()/2;
+ int[] intArray = new int[byteCount/4 + ((byteCount % 4 != 0) ? 1 : 0)];
+ for (int i = 0; i < byteCount; i++)
+ {
+ int oSStartPos = octetString.length() - (i + 1) * 2;
+ int currentByte = Integer.parseInt(octetString.substring(oSStartPos, oSStartPos + 2), 16);
+ intArray[i/4] += (currentByte & 0xFF) << ((i % 4) * 8);
+ }
+ return intArray;
+ }
+
+ /**
+ * Converts an octet string representation into a byte array as needed for the IAIK ECC library
+ * @param octetString rightmost byte is least significant byte
+ * @return byte[] rightmost byte is MOST significant byte
+ */
+ private static byte[] octetString2ByteArray(String octetString)
+ {
+ int byteCount = octetString.length()/2;
+ byte[] byteArray = new byte[byteCount];
+ for (int i = 0; i < byteCount; i++)
+ {
+ int oSStartPos = octetString.length() - (i + 1) * 2;
+ byteArray[byteCount - i - 1] = (byte) Integer.parseInt(octetString.substring(
+ oSStartPos, oSStartPos + 2), 16);
+ }
+ return byteArray;
+ }
+
+ /**
+ * Method evenStringLength.
+ * @param hexString
+ * @return String
+ */
+
+ private static String evenStringLength(String hexString)
+ {
+ return (hexString.length() % 2 != 0) ? "0" + hexString : hexString;
+ }
+
+ /**
+ * Method getChildElement.
+ * @param parent
+ * @param namespace
+ * @param localName
+ * @param instance
+ * @return Element
+ */
+
+ private static Element getChildElement(Element parent, String namespace, String localName,
+ int instance)
+ {
+ NodeList namedElements = parent.getElementsByTagNameNS(namespace, localName);
+ if (namedElements.getLength() < instance) return null;
+ return (Element)namedElements.item(instance - 1);
+ }
+
+ /**
+ * Method getChildElementText.
+ * @param parent Element
+ * @param namespace String
+ * @param localName String
+ * @param instance int
+ * @return String
+ */
+
+ private static String getChildElementText(Element parent, String namespace, String localName,
+ int instance)
+ {
+ Element child = getChildElement(parent, namespace, localName, instance);
+ if (child == null) return null;
+ NodeList childNodes = child.getChildNodes();
+ int nodeCount = 0;
+ while (nodeCount < childNodes.getLength())
+ {
+ Node currentNode = childNodes.item(nodeCount);
+ if (currentNode.getNodeType() == Node.TEXT_NODE) return currentNode.getNodeValue();
+ nodeCount++;
+ }
+ return null;
+ }
+
+ /**
+ * Method getInScopeNSAttrs.
+ * @param element element
+ * @return HashMap
+ */
+ public static HashMap getInScopeNSAttrs(Element element)
+ {
+ // Get all ancestors of element
+ Vector ancestors = new Vector();
+ ancestors.add(element);
+ Node currentAncestor = element;
+ while ((currentAncestor = currentAncestor.getParentNode()) != null &&
+ currentAncestor.getNodeType() == Node.ELEMENT_NODE)
+ {
+ ancestors.add(currentAncestor);
+ }
+
+ // Scan all ancestors for NS attributes
+ HashMap inScopeNSAttrs = new HashMap();
+ for (int i = ancestors.size() - 1; i >= 0; i--)
+ {
+ Element currentAncestorElem = (Element)ancestors.get(i);
+ NamedNodeMap attrs = currentAncestorElem.getAttributes();
+ for (int j = 0; j < attrs.getLength(); j++)
+ {
+ Attr currentAttr = (Attr)attrs.item(j);
+ String currentAttrName = currentAttr.getNodeName();
+ if ("xmlns".equals(currentAttrName) || currentAttrName.startsWith("xmlns:"))
+ {
+ inScopeNSAttrs.put(currentAttrName, currentAttr);
+ }
+ }
+ }
+
+ // Check if default NS attribute is in list; if value is empty remove it from list
+ Attr defaultNSAttr = (Attr)inScopeNSAttrs.get("xmlns");
+ if (defaultNSAttr != null && "".equals(defaultNSAttr.getValue())) inScopeNSAttrs.remove("xmlns");
+
+ return inScopeNSAttrs;
+ }
+} \ No newline at end of file
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/parser/ErrorResponseParser.java b/id.server/src/at/gv/egovernment/moa/id/auth/parser/ErrorResponseParser.java
new file mode 100644
index 000000000..4fbc58977
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/parser/ErrorResponseParser.java
@@ -0,0 +1,89 @@
+package at.gv.egovernment.moa.id.auth.parser;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.ParseException;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Parses an <code>&lt;InfoboxReadResponse&gt;</code>.
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+
+public class ErrorResponseParser {
+ //
+ // XPath namespace prefix shortcuts
+ //
+ /** Xpath prefix for reaching SecurityLayer 1.0 Namespaces */
+ private static final String SL10 = Constants.SL10_PREFIX + ":";
+ /** Xpath expression to the root element */
+ private static final String ROOT = "/" + SL10 + "ErrorResponse/";
+ /** Xpath expression to the ErrorCode element */
+ private static final String ERROR_CODE_XPATH =
+ ROOT + SL10 + "ErrorCode";
+ /** Xpath expression to the Info element */
+ private static final String ERROR_INFO_XPATH =
+ ROOT + SL10 + "Info";
+
+
+ /** This is the root element of the XML-Document provided by the Security Layer Card */
+ private Element errorElement;
+
+ /**
+ * Constructor for InfoboxReadResponseParser.
+ * A DOM-representation of the incoming String will be created
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as String
+ * @throws ParseException on any error
+ */
+ public ErrorResponseParser(String xmlResponse) throws ParseException {
+ try {
+ InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8"));
+ errorElement = DOMUtils.parseXmlValidating(s);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString()}, t);
+ }
+ }
+
+ /**
+ * Constructor for InfoboxReadResponseParser.
+ * A DOM-representation of the incoming Inputstream will be created
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as InputStream
+ * @throws ParseException on any error
+ */
+ public ErrorResponseParser(InputStream xmlResponse) throws ParseException {
+ try {
+ errorElement = DOMUtils.parseXmlValidating(xmlResponse);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString() }, t);
+ }
+ }
+
+ /**
+ * Method getErrorCode. returns the error code
+ * @return String
+ */
+ public String getErrorCode() {
+
+ return XPathUtils.getElementValue(errorElement,ERROR_CODE_XPATH,null);
+ }
+
+ /**
+ * Method getErrorInfo: returns the information about the error
+ * @return String
+ */
+ public String getErrorInfo() {
+
+ return XPathUtils.getElementValue(errorElement,ERROR_INFO_XPATH,null);
+ }
+
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java b/id.server/src/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java
new file mode 100644
index 000000000..f9ef54884
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java
@@ -0,0 +1,266 @@
+package at.gv.egovernment.moa.id.auth.parser;
+
+import java.security.interfaces.RSAPublicKey;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.traversal.NodeIterator;
+
+import at.gv.egovernment.moa.id.*;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.util.Base64Utils;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Parses an identity link <code>&lt;saml:Assertion&gt;</code>
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class IdentityLinkAssertionParser {
+
+ //
+ // XPath namespace prefix shortcuts
+ //
+
+ /** Xpath prefix for reaching PersonData Namespaces */
+ private static final String PDATA = Constants.PD_PREFIX + ":";
+ /** Xpath prefix for reaching SecurityLayer 1.0 Namespaces */
+ private static final String SL10 = Constants.SL10_PREFIX + ":";
+ /** Xpath prefix for reaching SAML Namespaces */
+ private static final String SAML = Constants.SAML_PREFIX + ":";
+ /** Xpath prefix for reaching XML-DSIG Namespaces */
+ private static final String DSIG = Constants.DSIG_PREFIX + ":";
+ /** Xpath prefix for reaching ECDS Namespaces */
+ private static final String ECDSA = Constants.ECDSA_PREFIX + ":";
+ /** Xpath expression to the root element */
+ private static final String ROOT = "/" + SAML + "Assertion/";
+ /** Xpath expression to the SAMLSubjectConfirmationData element */
+ private static final String SAML_SUBJECT_CONFIRMATION_DATA_XPATH =
+ ROOT
+ + SAML
+ + "AttributeStatement/"
+ + SAML
+ + "Subject/"
+ + SAML
+ + "SubjectConfirmation/"
+ + SAML
+ + "SubjectConfirmationData";
+ /** Xpath expression to the PersonData element */
+ private static final String PERSON_XPATH =
+ SAML_SUBJECT_CONFIRMATION_DATA_XPATH
+ + "/"
+ + PDATA
+ + "Person";
+ /** Xpath expression to the PersonData GivenName element */
+ private static final String PERSON_GIVEN_NAME_XPATH =
+ PERSON_XPATH
+ + "/"
+ + PDATA
+ + "Name/"
+ + PDATA
+ + "GivenName";
+ /** Xpath expression to the PersonData FamilyName element */
+ private static final String PERSON_FAMILY_NAME_XPATH =
+ PERSON_XPATH
+ + "/"
+ + PDATA
+ + "Name/"
+ + PDATA
+ + "FamilyName";
+ /** Xpath expression to the PersonData DateOfBirth element */
+ private static final String PERSON_DATE_OF_BIRTH_XPATH =
+ PERSON_XPATH
+ + "/"
+ + PDATA
+ + "DateOfBirth";
+ /** Xpath expression to the Identification element */
+ private static final String PERSON_IDENT_XPATH =
+ PERSON_XPATH
+ + "/"
+ + PDATA
+ + "Identification";
+
+ /** Xpath expression to the Identification Value element */
+ private static final String PERSON_IDENT_VALUE_XPATH =
+ PERSON_XPATH
+ + "/"
+ + PDATA
+ + "Identification/"
+ + PDATA
+ + "Value";
+ /** Xpath expression to the RSAKeyValue element */
+ private static final String RSA_KEY_VALUE_XPATH =
+ ROOT
+ + SAML
+ + "AttributeStatement/"
+ + SAML
+ + "Attribute/"
+ + SAML
+ + "AttributeValue/"
+ + DSIG
+ + "RSAKeyValue";
+ /** Xpath expression to the RSA Modulus element */
+ private static final String RSA_KEY_MODULUS_XPATH = DSIG + "Modulus";
+ /** Xpath expression to the RSA Exponent element */
+ private static final String RSA_KEY_EXPONENT_XPATH = DSIG + "Exponent";
+ /** Xpath expression to the DSIG X509Certificate element */
+ private static final String DSIG_CERTIFICATES_XPATH =
+ ROOT
+ + DSIG
+ + "Signature/"
+ + DSIG
+ + "KeyInfo/"
+ + DSIG
+ + "X509Data/"
+ + DSIG
+ + "X509Certificate";
+ /** Xpath expression to the DSIG Transforms element */
+ private static final String DSIG_REFERENCE_TRANSFORMATION_XPATH =
+ ROOT
+ + DSIG
+ + "Signature/"
+ + DSIG
+ + "SignedInfo/"
+ + DSIG
+ + "Reference/"
+ + DSIG
+ + "Transforms";
+
+ /**This is the root element of the XML-Document provided by the Security Layer Card*/
+ private Element assertionElem;
+
+ /**
+ * Constructor for <code>IdentityLinkAssertionParser</code>.
+ * A DOM-representation of the incoming String will be created
+ * @param xmlAssertion <code>&lt;saml:Assertion&gt;</code> as String
+ * @throws ParseException on any parsing error
+ */
+ public IdentityLinkAssertionParser(String xmlAssertion) throws ParseException {
+ try {
+ InputStream s = new ByteArrayInputStream(xmlAssertion.getBytes("UTF-8"));
+ assertionElem = DOMUtils.parseXmlValidating(s);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString()}, t);
+ }
+ }
+
+ /**
+ * Constructor for <code>IdentityLinkAssertionParser</code>.
+ * A DOM-representation of the incoming Inputstream will be created
+ * @param xmlAssertion <code>&lt;saml:Assertion&gt;</code> as InputStream
+ * @throws ParseException on any parsing error
+ */
+ public IdentityLinkAssertionParser(InputStream xmlAssertion) throws Exception {
+ try {
+ assertionElem = DOMUtils.parseXmlValidating(xmlAssertion);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString() }, t);
+ }
+ }
+
+ /**
+ * Parses the identity link from the <code>&lt;saml:Assertion&gt;</code>
+ * @return Identity link
+ * @throws ParseException on any parsing error
+ */
+
+ public IdentityLink parseIdentityLink() throws ParseException {
+ IdentityLink identityLink;
+ try {
+ identityLink = new IdentityLink();
+ //ÄNDERN: NUR der Identification-Teil
+ identityLink.setSamlAssertion(assertionElem);
+ identityLink.setPrPerson((Element)
+ XPathUtils.selectSingleNode(assertionElem, PERSON_XPATH));
+ identityLink.setIdentificationValue(
+ XPathUtils.getElementValue(assertionElem, PERSON_IDENT_VALUE_XPATH, ""));
+ identityLink.setGivenName(
+ XPathUtils.getElementValue(assertionElem, PERSON_GIVEN_NAME_XPATH, ""));
+ identityLink.setFamilyName(
+ XPathUtils.getElementValue(assertionElem, PERSON_FAMILY_NAME_XPATH, ""));
+ identityLink.setDateOfBirth(
+ XPathUtils.getElementValue(assertionElem, PERSON_DATE_OF_BIRTH_XPATH, ""));
+ NodeIterator dsigRefTransforms =
+ XPathUtils.selectNodeIterator(assertionElem, DSIG_REFERENCE_TRANSFORMATION_XPATH);
+ List transElems = new ArrayList();
+ Element transformsElem;
+ while ((transformsElem = (Element) dsigRefTransforms.nextNode()) != null) {
+ transElems.add(transformsElem);
+ }
+ Element[] result = new Element[transElems.size()];
+ transElems.toArray(result);
+ identityLink.setDsigReferenceTransforms(result);
+
+ identityLink.setPublicKey(getPublicKeys());
+
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString() }, t);
+ }
+
+ return identityLink;
+ }
+
+ /**
+ * Parses an array of Public Keys from the <code>&lt;InfoboxReadResponse&gt;</code>
+ * @return RSAPublicKey[]
+ * @throws IOException can occur when decoding the base64 values of the modulus and exponent
+ */
+ public PublicKey[] getPublicKeys() throws IOException{
+
+
+ List pubKeys = new ArrayList();
+ //Try to get RSA-Keys
+ NodeIterator rsaIter =
+ XPathUtils.selectNodeIterator(assertionElem, RSA_KEY_VALUE_XPATH);
+ Element rsaElem;
+ while ((rsaElem = (Element) rsaIter.nextNode()) != null) {
+ String modulus =
+ XPathUtils.getElementValue(rsaElem, RSA_KEY_MODULUS_XPATH, "");
+ String exponent =
+ XPathUtils.getElementValue(rsaElem, RSA_KEY_EXPONENT_XPATH, "");
+
+ RSAPublicKey resPub =
+ new iaik.security.rsa.RSAPublicKey(
+ new BigInteger(1, Base64Utils.decode(modulus, true)),
+ new BigInteger(1, Base64Utils.decode(exponent, true)));
+ pubKeys.add(resPub);}
+
+ PublicKey[] result = new PublicKey[pubKeys.size()];
+
+ pubKeys.toArray(result);
+ return result;
+
+ }
+ /**
+ * Parses a string array of decoded base64 certificates from
+ * the <code>&lt;InfoboxReadResponse&gt;</code> found in the dsig-signature
+ * @return String[] with raw-certificates from the dsig-signature keyinfo
+ * @throws Exception
+ */
+ public String[] getCertificates() throws Exception {
+ List certs = new ArrayList();
+ NodeIterator rsaIter =
+ XPathUtils.selectNodeIterator(assertionElem, DSIG_CERTIFICATES_XPATH);
+ Element certElem;
+ while ((certElem = (Element) rsaIter.nextNode()) != null) {
+ String content = DOMUtils.getText(certElem);
+ certs.add(new String(Base64Utils.decode(content, true)));
+ }
+ String[] result = new String[certs.size()];
+ certs.toArray(result);
+ return result;
+
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/parser/InfoboxReadResponseParser.java b/id.server/src/at/gv/egovernment/moa/id/auth/parser/InfoboxReadResponseParser.java
new file mode 100644
index 000000000..c1146218e
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/parser/InfoboxReadResponseParser.java
@@ -0,0 +1,110 @@
+package at.gv.egovernment.moa.id.auth.parser;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.AuthenticationException;
+import at.gv.egovernment.moa.id.ParseException;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Parses an <code>&lt;InfoboxReadResponse&gt;</code>.
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+
+public class InfoboxReadResponseParser {
+ //
+ // XPath namespace prefix shortcuts
+ //
+ /** Xpath prefix for reaching SecurityLayer 1.0 Namespaces */
+ private static final String SL10 = Constants.SL10_PREFIX + ":";
+ /** Xpath prefix for reaching SAML Namespaces */
+ private static final String SAML = Constants.SAML_PREFIX + ":";
+ /** Xpath expression to the root element */
+ private static final String ROOT = "/" + SL10 + "InfoboxReadResponse/";
+ /** Xpath expression to the SAML:Assertion element */
+ private static final String SAML_ASSERTION_XPATH = ROOT + SL10 + "BinaryFileData/" + SL10 + "XMLContent/" + SAML + "Assertion";
+
+ /** This is the root element of the XML-Document provided by the Security Layer Card*/
+ private Element infoBoxElem;
+
+ /**
+ * Constructor for InfoboxReadResponseParser.
+ * A DOM-representation of the incoming String will be created
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as String
+ * @throws ParseException on any parsing error
+ */
+ public InfoboxReadResponseParser(String xmlResponse) throws ParseException, AuthenticationException {
+
+ ErrorResponseParser erp = new ErrorResponseParser(xmlResponse);
+ if (erp.getErrorCode() != null) {
+ throw new AuthenticationException("auth.08", new Object[] { erp.getErrorCode(), erp.getErrorInfo()});
+ }
+
+ try {
+
+ InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8"));
+ infoBoxElem = DOMUtils.parseXmlValidating(s);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString()}, t);
+ }
+ }
+
+ /**
+ * Constructor for InfoboxReadResponseParser.
+ * A DOM-representation of the incoming Inputstream will be created
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as InputStream
+ * @throws ParseException on any parsing error
+ */
+ public InfoboxReadResponseParser(InputStream is) throws ParseException, AuthenticationException {
+
+ ErrorResponseParser erp = new ErrorResponseParser(is);
+ if (erp.getErrorCode() != null) {
+ throw new AuthenticationException("auth.08", new Object[] { erp.getErrorCode(), erp.getErrorInfo()});
+ }
+
+ try {
+
+ infoBoxElem = DOMUtils.parseXmlValidating(is);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString()}, t);
+ }
+ }
+
+ /**
+ * Parses the embedded <code>&lt;saml:Assertion&gt;</code> element from <code>&lt;InfoboxReadResponse&gt;</code>
+ * @return <code>&lt;saml:Assertion&gt;</code> as String
+ * @throws ParseException on any parsing error
+ */
+ public String parseSAMLAssertion() throws ParseException {
+ try {
+ Element samlAssertion = (Element) XPathUtils.selectSingleNode(infoBoxElem, SAML_ASSERTION_XPATH);
+ return DOMUtils.serializeNode(samlAssertion);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString()}, t);
+ }
+ }
+
+ /**
+ * Parses the identity link from the <code>&lt;saml:Assertion&gt;</code>
+ * @return Identity link
+ * @throws ParseException on any parsing error
+ */
+
+ public IdentityLink parseIdentityLink() throws ParseException {
+ String samlAssertionString = parseSAMLAssertion();
+ IdentityLinkAssertionParser ilParser = new IdentityLinkAssertionParser(samlAssertionString);
+ return ilParser.parseIdentityLink();
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParser.java b/id.server/src/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParser.java
new file mode 100644
index 000000000..7c4c01abe
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/parser/SAMLArtifactParser.java
@@ -0,0 +1,58 @@
+package at.gv.egovernment.moa.id.auth.parser;
+
+import java.io.IOException;
+
+import at.gv.egovernment.moa.id.ParseException;
+import at.gv.egovernment.moa.util.Base64Utils;
+
+/**
+ * Parser for a SAML artifact.
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class SAMLArtifactParser {
+ /** byte array containing the SamlArtifact bytes */
+ private byte[] samlArtifactBytes;
+
+ /**
+ * Constructor
+ * @param samlArtifact as String
+ * @throws ParseException on any parsing error
+ */
+ public SAMLArtifactParser(String samlArtifact) throws ParseException {
+ try {
+ samlArtifactBytes = Base64Utils.decode(samlArtifact, false);
+ }
+ catch (IOException ex) {
+ throw new ParseException("parser.02", new Object[] {ex.toString()}, ex);
+ }
+ }
+ /**
+ * Parses the type code.
+ * @return type code
+ * @throws ParseException when SAML artifact is invalid
+ */
+ public byte[] parseTypeCode() throws ParseException {
+ try {
+ byte[] typeCode = new byte[] {samlArtifactBytes[0], samlArtifactBytes[1]};
+ return typeCode;
+ }
+ catch (Throwable ex) {
+ throw new ParseException("parser.02", new Object[] {ex.toString()}, ex);
+ }
+ }
+ /**
+ * Parses the assertion handle.
+ * @return assertion handle
+ * @throws ParseException when SAML artifact is invalid
+ */
+ public String parseAssertionHandle() throws ParseException {
+ try {
+ return new String(samlArtifactBytes, 22, 20);
+ }
+ catch (Throwable ex) {
+ throw new ParseException("parser.02", new Object[] {ex.toString()}, ex);
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java b/id.server/src/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java
new file mode 100644
index 000000000..c74dc64e8
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/parser/VerifyXMLSignatureResponseParser.java
@@ -0,0 +1,159 @@
+package at.gv.egovernment.moa.id.auth.parser;
+
+import iaik.utils.Base64InputStream;
+import iaik.x509.X509Certificate;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.*;
+import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Parses a <code>&lt;VerifyXMLSignatureResponse&gt;</code> returned by
+ * MOA-SPSS.
+ * This class implements the Singleton pattern
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+
+
+public class VerifyXMLSignatureResponseParser {
+ //
+ // XPath namespace prefix shortcuts
+ //
+ /** Xpath prefix for reaching MOA Namespaces */
+ private static final String MOA = Constants.MOA_PREFIX + ":";
+ /** Xpath prefix for reaching DSIG Namespaces */
+ private static final String DSIG = Constants.DSIG_PREFIX + ":";
+ /** Xpath prefix for reaching SecurityLayer 1.1 Namespaces */
+ private static final String SL11 = Constants.SL11_PREFIX + ":";
+ /** Xpath expression to the root element */
+ private static final String ROOT = "/" + MOA + "VerifyXMLSignatureResponse/";
+
+ /** Xpath expression to the X509SubjectName element */
+ private static final String DSIG_SUBJECT_NAME_XPATH =
+ ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" +
+ DSIG + "X509SubjectName";
+ /** Xpath expression to the X509Certificate element */
+ private static final String DSIG_X509_CERTIFICATE_XPATH =
+ ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" +
+ DSIG + "X509Certificate";
+ /** Xpath expression to the PublicAuthority element */
+ private static final String PUBLIC_AUTHORITY_XPATH =
+ ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" +
+ MOA + "PublicAuthority";
+ /** Xpath expression to the PublicAuthorityCode element */
+ private static final String PUBLIC_AUTHORITY_CODE_XPATH =
+ PUBLIC_AUTHORITY_XPATH + "/" + MOA + "Code";
+ /** Xpath expression to the QualifiedCertificate element */
+ private static final String QUALIFIED_CERTIFICATE_XPATH =
+ ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" +
+ SL11 + "QualifiedCertificate";
+
+ /** Xpath expression to the SignatureCheckCode element */
+ private static final String SIGNATURE_CHECK_CODE_XPATH =
+ ROOT + MOA + "SignatureCheck/" + MOA + "Code";
+ /** Xpath expression to the XMLDSIGManifestCheckCode element */
+ private static final String XMLDSIG_MANIFEST_CHECK_CODE_XPATH =
+ ROOT + MOA + "XMLDSIGManifestCheck/" + MOA + "Code";
+ /** Xpath expression to the CertificateCheckCode element */
+ private static final String CERTIFICATE_CHECK_CODE_XPATH =
+ ROOT + MOA + "CertificateCheck/" + MOA + "Code";
+
+
+ /** This is the root element of the XML-Document provided by the Security Layer Card*/
+ private Element verifyXMLSignatureResponse;
+
+ /**
+ * Constructor for VerifyXMLSignatureResponseParser.
+ * A DOM-representation of the incoming String will be created
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as String
+ * @throws ParseException on any parsing error
+ */
+ public VerifyXMLSignatureResponseParser(String xmlResponse) throws ParseException{
+ try {
+ InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8"));
+
+ verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(s);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", null, t);
+ }
+ }
+
+ /**
+ * Constructor for VerifyXMLSignatureResponseParser.
+ * A DOM-representation of the incoming Inputstream will be created
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as InputStream
+ * @throws Exception on any parsing error
+ */
+ public VerifyXMLSignatureResponseParser(InputStream xmlResponse) throws Exception
+ {
+ try {
+ verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(xmlResponse);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", null, t);
+ }
+ }
+
+ /**
+ * Constructor for VerifyXMLSignatureResponseParser.
+ * The incoming Element will be used for further operations
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as Element
+ */
+ public VerifyXMLSignatureResponseParser(Element xmlResponse)
+ {
+ verifyXMLSignatureResponse =xmlResponse;
+
+ }
+
+ /**
+ * Parse identity link from <code>&lt;InfoboxReadResponse&gt;</code>
+ * @return Identity link
+ * @throws ParseException on any parsing error
+ */
+
+ public VerifyXMLSignatureResponse parseData() throws ParseException {
+ VerifyXMLSignatureResponse respData=new VerifyXMLSignatureResponse();
+
+ try {
+
+ respData.setXmlDsigSubjectName(XPathUtils.getElementValue(verifyXMLSignatureResponse,DSIG_SUBJECT_NAME_XPATH,""));
+ Element e = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,QUALIFIED_CERTIFICATE_XPATH);
+ respData.setQualifiedCertificate(e!=null);
+
+ Base64InputStream in = new Base64InputStream(new ByteArrayInputStream(XPathUtils.getElementValue(
+ verifyXMLSignatureResponse,DSIG_X509_CERTIFICATE_XPATH,"").getBytes("UTF-8")),true);
+
+ respData.setX509certificate(new X509Certificate(in));
+
+ Element publicAuthority = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_CODE_XPATH);
+ respData.setPublicAuthority(publicAuthority != null);
+ respData.setPublicAuthorityCode(XPathUtils.getElementValue(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_CODE_XPATH,""));
+ respData.setSignatureCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNATURE_CHECK_CODE_XPATH,"")).intValue());
+
+ String xmlDsigCheckCode = XPathUtils.getElementValue(verifyXMLSignatureResponse,XMLDSIG_MANIFEST_CHECK_CODE_XPATH,null);
+ if (xmlDsigCheckCode!=null)
+ {
+ respData.setXmlDSIGManigest(true);
+ respData.setXmlDSIGManifestCheckCode(new Integer(xmlDsigCheckCode).intValue());
+ }
+ else
+ respData.setXmlDSIGManigest(false);
+ respData.setCertificateCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,CERTIFICATE_CHECK_CODE_XPATH,"")).intValue());
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", null, t);
+ }
+ return respData;
+ }
+
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java
new file mode 100644
index 000000000..3a1cab4be
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java
@@ -0,0 +1,117 @@
+package at.gv.egovernment.moa.id.auth.servlet;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.WrongParametersException;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.URLDecoder;
+
+/**
+ * Base class for MOA-ID Auth Servlets, providing standard error handling
+ * and constant names.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {
+
+
+ /**
+ * Handles an error. <br>
+ * <ul>
+ * <li>Logs the error</li>
+ * <li>Places error message and exception thrown into the request
+ * as request attributes (to be used by <code>"/errorpage.jsp"</code>)</li>
+ * <li>Sets HTTP status 500 (internal server error)</li>
+ * </ul>
+ *
+ * @param errorMessage error message
+ * @param exceptionThrown exception thrown
+ * @param req servlet request
+ * @param resp servlet response
+ */
+ protected void handleError(
+ String errorMessage, Throwable exceptionThrown, HttpServletRequest req, HttpServletResponse resp) {
+
+ if (exceptionThrown != null)
+ Logger.error(errorMessage, exceptionThrown);
+ else
+ Logger.error(errorMessage);
+ req.setAttribute("ErrorMessage", errorMessage);
+ req.setAttribute("ExceptionThrown", exceptionThrown);
+ resp.setStatus(500);
+ }
+ /**
+ * Handles a <code>WrongParametersException</code>.
+ * @param req servlet request
+ * @param resp servlet response
+ */
+ protected void handleWrongParameters(WrongParametersException ex, HttpServletRequest req, HttpServletResponse resp) {
+ Logger.error(ex.toString());
+ req.setAttribute("WrongParameters", "true");
+ resp.setStatus(500);
+ }
+
+ /**
+ * Logs all servlet parameters for debugging purposes.
+ */
+ protected void logParameters(HttpServletRequest req) {
+ for (Enumeration enum = req.getParameterNames(); enum.hasMoreElements(); ) {
+ String parname = (String)enum.nextElement();
+ Logger.debug("Parameter " + parname + req.getParameter(parname));
+ }
+ }
+ /**
+ * Parses the request input stream for parameters,
+ * assuming parameters are encoded UTF-8.
+ * @param req servlet request
+ * @return mapping parameter name -> value
+ */
+ protected Map getParameters(HttpServletRequest req) throws IOException {
+ Map parameters = new HashMap();
+ InputStream in = req.getInputStream();
+ String paramName;
+ String paramValueURLEncoded;
+ do {
+ paramName = new String(readBytesUpTo(in, '='));
+ if (paramName.length() > 0) {
+ paramValueURLEncoded = readBytesUpTo(in, '&');
+ String paramValue = URLDecoder.decode(paramValueURLEncoded, "UTF-8");
+ parameters.put(paramName, paramValue);
+ }
+ }
+ while (paramName.length() > 0);
+ in.close();
+
+ return parameters;
+ }
+ /**
+ * Reads bytes up to a delimiter, consuming the delimiter.
+ * @param in input stream
+ * @param delimiter delimiter character
+ * @return String constructed from the read bytes
+ * @throws IOException
+ */
+ protected String readBytesUpTo(InputStream in, char delimiter) throws IOException {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ boolean done = false;
+ int b;
+ while (! done && (b = in.read()) >= 0) {
+ if (b == delimiter)
+ done = true;
+ else
+ bout.write(b);
+ }
+ return bout.toString();
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/servlet/ConfigurationServlet.java b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/ConfigurationServlet.java
new file mode 100644
index 000000000..554819f73
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/ConfigurationServlet.java
@@ -0,0 +1,74 @@
+package at.gv.egovernment.moa.id.auth.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egovernment.moa.id.auth.MOAIDAuthInitializer;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Servlet requested for updating the MOA-ID Auth configuration from configuration file
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ConfigurationServlet extends HttpServlet {
+ /** Constant for the DTD-Doc type */
+ private static final String DOC_TYPE =
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n";
+
+ /**
+ * Handle a HTTP GET request, used to indicated that the MOA
+ * configuration needs to be updated (reloaded).
+ *
+ * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
+ */
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ MOAIDMessageProvider msg = MOAIDMessageProvider.getInstance();
+ PrintWriter out;
+
+ response.setContentType("text/html");
+ out = response.getWriter();
+ out.println(DOC_TYPE);
+ out.println("<head><title>MOA configuration update</title></head>");
+ out.println("<body bgcolor=\"#FFFFFF\">");
+ try {
+ MOAIDAuthInitializer.initialized=false;
+ MOAIDAuthInitializer.initialize();
+ String message = msg.getMessage("config.00", null);
+ Logger.info(message);
+ out.println("<p><b>");
+ out.println(message);
+ out.println("</b></p>");
+ } catch (Throwable t) {
+ String errorMessage = msg.getMessage("config.04", null);
+ Logger.error(errorMessage, t);
+ out.println("<p><b>");
+ out.println(errorMessage);
+ out.println("</b></p>");
+ }
+ out.println("</body>");
+
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Do the same as <code>doGet</code>.
+ *
+ * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest, HttpServletResponse)
+ */
+ public void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ doGet(request, response);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/servlet/GetAuthenticationDataService.java b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/GetAuthenticationDataService.java
new file mode 100644
index 000000000..c41b514c8
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/GetAuthenticationDataService.java
@@ -0,0 +1,135 @@
+package at.gv.egovernment.moa.id.auth.servlet;
+
+import java.util.Calendar;
+
+import org.apache.axis.AxisFault;
+import org.w3c.dom.Element;
+
+import org.w3c.dom.NodeList;
+
+import at.gv.egovernment.moa.id.AuthenticationException;
+import at.gv.egovernment.moa.id.MOAIDException;
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.SAMLResponseBuilder;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.DateTimeUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Web service for picking up authentication data created in the MOA-ID Auth component.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ * @see at.gv.egovernment.moa.id.auth.AuthenticationServer#getAuthenticationData
+ */
+public class GetAuthenticationDataService implements Constants {
+
+ /**
+ * Constructor for GetAuthenticationDataService.
+ */
+ public GetAuthenticationDataService() {
+ super();
+ }
+
+ /**
+ * Takes a <code>lt;samlp:Request&gt;</code> containing a
+ * <code>SAML artifact</code> and returns the corresponding
+ * authentication data <code>lt;saml:Assertion&gt;</code>
+ * (obtained from the <code>AuthenticationServer</code>),
+ * enclosed in a <code>lt;samlp:Response&gt;</code>.
+ * <br/>Bad requests are mapped into various <code>lt;samlp:StatusCode&gt;</code>s,
+ * possibly containing enclosed sub-<code>lt;samlp:StatusCode&gt;</code>s.
+ * The status codes are defined in the SAML specification.
+ *
+ * @param requests request elements of type <code>lt;samlp:Request&gt;</code>;
+ * only 1 request element is allowed
+ * @return response element of type <code>lt;samlp:Response&gt;</code>,
+ * packed into an <code>Element[]</code>
+ * @throws AxisFault thrown when an error occurs in assembling the
+ * <code>lt;samlp:Response&gt;</code>
+ */
+ public Element[] Request(Element[] requests)
+ throws AxisFault {
+
+ Element request = requests[0];
+ Element[] responses = new Element[1];
+ String requestID = "";
+ String statusCode = "";
+ String subStatusCode = null;
+ String statusMessageCode = null;
+ String statusMessage = null;
+ String samlAssertion = "";
+ if (requests.length > 1) {
+ // more than 1 request given as parameter
+ statusCode = "samlp:Requester";
+ subStatusCode = "samlp:TooManyResponses";
+ statusMessageCode = "1201";
+ }
+ else {
+ try {
+ DOMUtils.validateElement(request, ALL_SCHEMA_LOCATIONS, null);
+ NodeList samlArtifactList = XPathUtils.selectNodeList(request, "samlp:AssertionArtifact");
+ if (samlArtifactList.getLength() == 0) {
+ // no SAML artifact given in request
+ statusCode = "samlp:Requester";
+ statusMessageCode = "1202";
+ }
+ else if (samlArtifactList.getLength() > 1) {
+ // too many SAML artifacts given in request
+ statusCode = "samlp:Requester";
+ subStatusCode = "samlp:TooManyResponses";
+ statusMessageCode = "1203";
+ }
+ else {
+ Element samlArtifactElem = (Element)samlArtifactList.item(0);
+ requestID = samlArtifactElem.getAttribute("RequestID");
+ String samlArtifact = DOMUtils.getText(samlArtifactElem);
+ try {
+ AuthenticationData authData = AuthenticationServer.getInstance().
+ getAuthenticationData(samlArtifact);
+ // success
+ samlAssertion = authData.getSamlAssertion();
+ statusCode = "samlp:Success";
+ statusMessageCode = "1200";
+ }
+ catch (AuthenticationException ex) {
+ // no authentication data for given SAML artifact
+ statusCode = "samlp:Requester";
+ subStatusCode = "samlp:ResourceNotRecognized";
+ statusMessage = ex.toString();
+ }
+ }
+ }
+ catch (Throwable t) {
+ // invalid request format
+ statusCode = "samlp:Requester";
+ statusMessageCode = "1204";
+ }
+ }
+ try {
+ String responseID = Random.nextRandom();
+ String issueInstant = DateTimeUtils.buildDateTime(Calendar.getInstance());
+ if (statusMessage == null)
+ statusMessage = MOAIDMessageProvider.getInstance().getMessage(statusMessageCode, null);
+ responses[0] = new SAMLResponseBuilder().build(
+ responseID, requestID, issueInstant, statusCode, subStatusCode, statusMessage, samlAssertion);
+ }
+ catch (MOAIDException e) {
+ AxisFault fault = AxisFault.makeFault(e);
+ fault.setFaultDetail(new Element[] { e.toErrorResponse()});
+ throw fault;
+ }
+ catch (Throwable t) {
+ MOAIDException e = new MOAIDException("1299", null, t);
+ AxisFault fault = AxisFault.makeFault(e);
+ fault.setFaultDetail(new Element[] { e.toErrorResponse()});
+ throw fault;
+ }
+ return responses;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/servlet/SelectBKUServlet.java b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/SelectBKUServlet.java
new file mode 100644
index 000000000..50ca21c69
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/SelectBKUServlet.java
@@ -0,0 +1,95 @@
+package at.gv.egovernment.moa.id.auth.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.MOAIDAuthInitializer;
+import at.gv.egovernment.moa.id.auth.WrongParametersException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Servlet requested for selecting a BKU.
+ * <br>In case of {@link AuthConfigurationProvider#getBKUSelectionType}==HTMLComplete,
+ * the browser is redirected to the configured "BKU-Auswahl-URL".
+ * <br>In case of {@link AuthConfigurationProvider#getBKUSelectionType}==HTMLSelect,
+ * the list of available BKU's is fetched from a BKU-Auswahl server, and presented
+ * to the user in an HTML form.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class SelectBKUServlet extends AuthServlet {
+
+ /**
+ * Calls the web application initializer.
+ *
+ * @see javax.servlet.Servlet#init(ServletConfig)
+ */
+ public void init(ServletConfig servletConfig) throws ServletException {
+ try {
+ MOAIDAuthInitializer.initialize();
+ Logger.info(MOAIDMessageProvider.getInstance().getMessage("init.00", null));
+ }
+ catch (Exception ex) {
+ Logger.fatal(MOAIDMessageProvider.getInstance().getMessage("init.02", null), ex);
+ throw new ServletException(ex);
+ }
+ }
+
+ /**
+ * Responds with an HTML form which requests the user to choose a BKU.
+ */
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ Logger.debug("GET SelectBKU");
+ String authURL =
+ req.getScheme() + "://" +
+ req.getServerName() + ":" +
+ req.getServerPort() +
+ req.getContextPath() + "/";
+ String target = req.getParameter(PARAM_TARGET);
+ String oaURL = req.getParameter(PARAM_OA);
+ String bkuSelectionTemplateURL = req.getParameter(PARAM_BKUTEMPLATE);
+ String templateURL = req.getParameter(PARAM_TEMPLATE);
+ resp.setHeader(HEADER_EXPIRES,HEADER_VALUE_EXPIRES);
+ resp.setHeader(HEADER_PRAGMA,HEADER_VALUE_PRAGMA);
+ resp.setHeader(HEADER_CACHE_CONTROL,HEADER_VALUE_CACHE_CONTROL);
+ resp.addHeader(HEADER_CACHE_CONTROL,HEADER_VALUE_CACHE_CONTROL_IE);
+
+ try {
+ String returnValue = AuthenticationServer.getInstance().selectBKU(
+ authURL, target, oaURL, bkuSelectionTemplateURL, templateURL);
+ String bkuSelectionType = AuthConfigurationProvider.getInstance().getBKUSelectionType();
+ if (bkuSelectionType.equals(AuthConfigurationProvider.BKU_SELECTION_TYPE_HTMLCOMPLETE)) {
+ // bkuSelectionType==HTMLComplete
+ String redirectURL = returnValue;
+ resp.sendRedirect(redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+ }
+ else {
+ // bkuSelectionType==HTMLSelect
+ String htmlForm = returnValue;
+ resp.setContentType("text/html");
+ PrintWriter out = new PrintWriter(resp.getOutputStream());
+ out.print(htmlForm);
+ out.flush();
+ Logger.debug("Finished GET SelectBKU");
+ }
+ }
+ catch (WrongParametersException ex) {
+ handleWrongParameters(ex, req, resp);
+ }
+ catch (Throwable ex) {
+ handleError(null, ex, req, resp);
+ }
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/servlet/StartAuthenticationServlet.java b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/StartAuthenticationServlet.java
new file mode 100644
index 000000000..2ea43935b
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/StartAuthenticationServlet.java
@@ -0,0 +1,102 @@
+package at.gv.egovernment.moa.id.auth.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egovernment.moa.id.MOAIDException;
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.MOAIDAuthInitializer;
+import at.gv.egovernment.moa.id.auth.WrongParametersException;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Servlet requested for starting a MOA ID authentication session.
+ * Utilizes the {@link AuthenticationServer}.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ * @see AuthenticationServer#startAuthentication
+ */
+public class StartAuthenticationServlet extends AuthServlet {
+
+ /**
+ * Responds with an HTML form which upon submit requests the identity link
+ * from the security layer implementation.
+ * <br>
+ * Response:
+ * <ul>
+ * <li>Content type: <code>"text/html"</code></li>
+ * <li>Content: see return value of {@link AuthenticationServer#startAuthentication}</li>
+ * <li>Error status: <code>500</code>
+ * </ul>
+ * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ Logger.debug("GET StartAuthentication");
+ String authURL =
+ req.getScheme() + "://" +
+ req.getServerName() + ":" +
+ req.getServerPort() +
+ req.getContextPath() + "/";
+ String target = req.getParameter(PARAM_TARGET);
+ String oaURL = req.getParameter(PARAM_OA);
+ String bkuURL = req.getParameter(PARAM_BKU);
+ String templateURL = req.getParameter(PARAM_TEMPLATE);
+ String sessionID = req.getParameter(PARAM_SESSIONID);
+ resp.setHeader(HEADER_EXPIRES,HEADER_VALUE_EXPIRES);
+ resp.setHeader(HEADER_PRAGMA,HEADER_VALUE_PRAGMA);
+ resp.setHeader(HEADER_CACHE_CONTROL,HEADER_VALUE_CACHE_CONTROL);
+ resp.addHeader(HEADER_CACHE_CONTROL,HEADER_VALUE_CACHE_CONTROL_IE);
+ try {
+ String getIdentityLinkForm =
+ AuthenticationServer.getInstance().startAuthentication(authURL, target, oaURL, templateURL, bkuURL, sessionID);
+ resp.setContentType("text/html");
+ PrintWriter out = new PrintWriter(resp.getOutputStream());
+ out.print(getIdentityLinkForm);
+ out.flush();
+ Logger.debug("Finished GET StartAuthentication");
+ }
+ catch (WrongParametersException ex) {
+ handleWrongParameters(ex, req, resp);
+ }
+ catch (MOAIDException ex) {
+ handleError(null, ex, req, resp);
+ }
+ }
+
+
+ /**
+ * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ doGet(req, resp);
+ }
+
+
+ /**
+ * Calls the web application initializer.
+ *
+ * @see javax.servlet.Servlet#init(ServletConfig)
+ */
+ public void init(ServletConfig servletConfig) throws ServletException {
+ try {
+ MOAIDAuthInitializer.initialize();
+ Logger.info(MOAIDMessageProvider.getInstance().getMessage("init.00", null));
+ }
+ catch (Exception ex) {
+ Logger.fatal(MOAIDMessageProvider.getInstance().getMessage("init.02", null), ex);
+ throw new ServletException(ex);
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java
new file mode 100644
index 000000000..8d16f73dd
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java
@@ -0,0 +1,110 @@
+package at.gv.egovernment.moa.id.auth.servlet;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egovernment.moa.id.MOAIDException;
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Servlet requested for verifying the signed authentication block
+ * provided by the security layer implementation.
+ * Utilizes the {@link AuthenticationServer}.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class VerifyAuthenticationBlockServlet extends AuthServlet {
+
+
+ /**
+ * Constructor for VerifyAuthenticationBlockServlet.
+ */
+ public VerifyAuthenticationBlockServlet() {
+ super();
+ }
+
+ /**
+ * GET requested by security layer implementation to verify
+ * that data URL resource is available.
+ * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ Logger.debug("GET VerifyAuthenticationBlock");
+ }
+
+ /**
+ * Verifies the signed authentication block and redirects the browser
+ * to the online application requested, adding a parameter needed for
+ * retrieving the authentication data.
+ * <br>
+ * Request parameters:
+ * <ul>
+ * <li>MOASessionID: ID of associated authentication session</li>
+ * <li>XMLResponse: <code>&lt;CreateXMLSignatureResponse&gt;</code></li>
+ * </ul>
+ * Response:
+ * <ul>
+ * <li>Status: <code>302</code></li>
+ * <li>Header <code>"Location"</code>: URL of the online application requested, with
+ * parameters <code>"Target"</code> and <code>"SAMLArtifact"</code> added</li>
+ * <li>Error status: <code>500</code>
+ * </ul>
+ * @see AuthenticationServer#verifyAuthenticationBlock
+ * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ Logger.debug("POST VerifyAuthenticationBlock");
+ Map parameters = getParameters(req);
+ String sessionID = req.getParameter(PARAM_SESSIONID);
+ String createXMLSignatureResponse = (String)parameters.get(PARAM_XMLRESPONSE);
+ // debug output
+ AuthenticationServer.debugOutputXMLFile("CreateXMLSignatureResponse.xml", createXMLSignatureResponse);
+ try {
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+ String samlArtifactBase64 =
+ AuthenticationServer.getInstance().verifyAuthenticationBlock(sessionID, createXMLSignatureResponse);
+ String redirectURL = session.getOAURLRequested();
+ redirectURL = addURLParameter(redirectURL, PARAM_TARGET, session.getTarget());
+ redirectURL = addURLParameter(redirectURL, PARAM_SAMLARTIFACT, URLEncoder.encode(samlArtifactBase64));
+ redirectURL = resp.encodeRedirectURL(redirectURL);
+ resp.setStatus(302);
+ resp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+ }
+ catch (WrongParametersException ex) {
+ handleWrongParameters(ex, req, resp);
+ }
+ catch (MOAIDException ex) {
+ handleError(null, ex, req, resp);
+ }
+
+ }
+ /**
+ * Adds a parameter to a URL.
+ * @param url the URL
+ * @param paramname parameter name
+ * @param paramvalue parameter value
+ * @return the URL with parameter added
+ */
+ private static String addURLParameter(String url, String paramname, String paramvalue) {
+ String param = paramname + "=" + paramvalue;
+ if (url.indexOf("?") < 0)
+ return url + "?" + param;
+ else
+ return url + "&" + param;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java
new file mode 100644
index 000000000..d3a28c7d4
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java
@@ -0,0 +1,97 @@
+package at.gv.egovernment.moa.id.auth.servlet;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egovernment.moa.id.MOAIDException;
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Servlet requested for verifying the identity link
+ * provided by the security layer implementation.
+ * Utilizes the {@link AuthenticationServer}.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class VerifyIdentityLinkServlet extends AuthServlet {
+
+ /**
+ * Constructor for VerifyIdentityLinkServlet.
+ */
+ public VerifyIdentityLinkServlet() {
+ super();
+ }
+
+ /**
+ * GET requested by security layer implementation to verify
+ * that data URL resource is available.
+ * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ Logger.debug("GET VerifyIdentityLink");
+ }
+
+ /**
+ * Verifies the identity link and responds with a new
+ * <code>CreateXMLSignatureRequest</code>.
+ * <br>
+ * Request parameters:
+ * <ul>
+ * <li>MOASessionID: ID of associated authentication session</li>
+ * <li>XMLResponse: <code>&lt;InfoboxReadResponse&gt;</code></li>
+ * </ul>
+ * Response:
+ * <ul>
+ * <li>Content type: <code>"text/xml"</code></li>
+ * <li>Content: see return value of {@link AuthenticationServer#verifyIdentityLink}</li>
+ * <li>Error status: <code>500</code>
+ * </ul>
+ * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ Logger.debug("POST VerifyIdentityLink");
+ Map parameters = getParameters(req);
+ String sessionID = req.getParameter(PARAM_SESSIONID);
+ String infoboxReadResponse = (String)parameters.get(PARAM_XMLRESPONSE);
+ // debug output
+ AuthenticationServer.debugOutputXMLFile("InfoboxReadResponse.xml", infoboxReadResponse);
+ try {
+ String createXMLSignatureRequest =
+ AuthenticationServer.getInstance().verifyIdentityLink(sessionID, infoboxReadResponse);
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+ resp.setStatus(307);
+ String dataURL = new DataURLBuilder().buildDataURL(
+ session.getAuthURL(), AuthenticationServer.REQ_VERIFY_AUTH_BLOCK, sessionID);
+ resp.addHeader("Location", dataURL);
+ resp.setContentType("text/xml");
+ // debug output
+ AuthenticationServer.debugOutputXMLFile("CreateXMLSignatureRequest.xml", createXMLSignatureRequest);
+ OutputStream out = resp.getOutputStream();
+ out.write(createXMLSignatureRequest.getBytes("UTF-8"));
+ out.flush();
+ out.close();
+ Logger.debug("Finished POST VerifyIdentityLink");
+ }
+ catch (WrongParametersException ex) {
+ handleWrongParameters(ex, req, resp);
+ }
+ catch (MOAIDException ex) {
+ handleError(null, ex, req, resp);
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java b/id.server/src/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java
new file mode 100644
index 000000000..e596e79a4
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java
@@ -0,0 +1,106 @@
+package at.gv.egovernment.moa.id.auth.validator;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse;
+import at.gv.egovernment.moa.id.auth.data.SAMLAttribute;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ *
+ * This class is used to validate an {@link CreateXMLSignatureResponse}
+ * returned by the security layer.
+ * This class implements the Singleton pattern.
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class CreateXMLSignatureResponseValidator {
+
+ /** Xpath prefix for reaching SecurityLayer 1.0 Namespaces */
+ private static final String SAML = Constants.SAML_PREFIX + ":";
+ /** Xpath prefix for reaching XML-DSIG Namespaces */
+ private static final String DSIG = Constants.DSIG_PREFIX + ":";
+ /** Xpath expression to the SAML:Assertion element */
+ private static final String ROOT = SAML + "Assertion";
+ /** Xpath expression to the SAML:NameIdentifier element */
+ private static final String SAML_SUBJECT_NAME_IDENTIFIER_XPATH =
+ SAML + "AttributeStatement/" + SAML + "Subject/" +
+ SAML + "NameIdentifier";
+ /** Xpath expression to the SAML:Attribute element */
+ private static final String SAML_ATTRIBUTE_XPATH =
+ ROOT + "/" + SAML + "AttributeStatement/" + SAML + "Attribute";
+ /** Xpath expression to the SAML:AttributeValue element */
+ private static final String SAML_ATTRIBUTE_VALUE_XPATH =
+ SAML + "AttributeValue";
+
+
+ /** Singleton instance. <code>null</code>, if none has been created. */
+ private static CreateXMLSignatureResponseValidator instance;
+
+ /**
+ * Constructor for a singleton CreateXMLSignatureResponseValidator.
+ * @return an instance of CreateXMLSignatureResponseValidator
+ * @throws ValidateException if no instance can be created
+ */
+ public static synchronized CreateXMLSignatureResponseValidator getInstance()
+ throws ValidateException {
+ if (instance == null) {
+ instance = new CreateXMLSignatureResponseValidator();
+ }
+ return instance;
+ }
+
+
+ /**
+ * The Method validate is used for validating an explicit {@link CreateXMLSignatureResponse}
+ * @param createXMLSignatureResponse
+ * @param gbTarget
+ * @param oaURL
+ * @throws ValidateException
+ */
+ public void validate(CreateXMLSignatureResponse createXMLSignatureResponse, String gbTarget, String oaURL)
+ throws ValidateException {
+
+ // A3.056: more then one /saml:Assertion/saml:AttributeStatement/saml:Subject/saml:NameIdentifier
+
+ XPathUtils.selectNodeList(createXMLSignatureResponse.getSamlAssertion(),SAML_SUBJECT_NAME_IDENTIFIER_XPATH);
+
+ SAMLAttribute[] samlattributes = createXMLSignatureResponse.getSamlAttributes();
+ boolean foundOA = false;
+ boolean foundGB = false;
+ for (int i = 0; i < samlattributes.length; i++)
+ {
+ if (samlattributes[i].getName().equals("Geschäftsbereich"))
+ if (samlattributes[i].getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#"))
+
+ {
+ foundGB = true;
+ if (!gbTarget.equals(samlattributes[i].getValue()))
+ {
+ throw new ValidateException("validator.13", null);
+ }
+ }
+ else throw new ValidateException("validator.12", null);
+ if (samlattributes[i].getName().equals("OA"))
+ if (samlattributes[i].getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#"))
+ {
+ foundOA = true;
+ if (!oaURL.equals(samlattributes[i].getValue())) // CHECKS für die AttributeVALUES fehlen noch
+ {
+ throw new ValidateException("validator.16", new Object[] {":gefunden wurde '" + oaURL + "', erwartet wurde '" + samlattributes[i].getValue()});
+ }
+
+ }
+ else throw new ValidateException("validator.15", null);
+ }
+ if (!foundOA) throw new ValidateException("validator.14", null);
+ if (!foundGB) throw new ValidateException("validator.11", null);
+
+ //Check if dsig:Signature exists
+ Element dsigSignature = (Element) XPathUtils.selectSingleNode(createXMLSignatureResponse.getSamlAssertion(),DSIG + "Signature");
+ if (dsigSignature==null) throw new ValidateException("validator.05", null);
+
+
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/validator/IdentityLinkValidator.java b/id.server/src/at/gv/egovernment/moa/id/auth/validator/IdentityLinkValidator.java
new file mode 100644
index 000000000..42e3e946f
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/validator/IdentityLinkValidator.java
@@ -0,0 +1,156 @@
+package at.gv.egovernment.moa.id.auth.validator;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ *
+ * This class is used to validate an {@link IdentityLink}
+ * returned by the security layer
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class IdentityLinkValidator implements Constants {
+
+ //
+ // XPath namespace prefix shortcuts
+ //
+ /** Xpath prefix for reaching PersonData Namespaces */
+ private static final String PDATA = PD_PREFIX + ":";
+ /** Xpath prefix for reaching SAML Namespaces */
+ private static final String SAML = SAML_PREFIX + ":";
+ /** Xpath prefix for reaching XML-DSIG Namespaces */
+ private static final String DSIG = DSIG_PREFIX + ":";
+ /** Xpath prefix for reaching ECDSA Namespaces */
+ private static final String ECDSA = ECDSA_PREFIX + ":";
+ /** Xpath expression to the root element */
+ private static final String ROOT = "/" + SAML + "Assertion/";
+ /** Xpath expression to the SAML:SubjectConfirmationData element */
+ private static final String SAML_SUBJECT_CONFIRMATION_DATA_XPATH =
+ ROOT
+ + SAML
+ + "AttributeStatement/"
+ + SAML
+ + "Subject/"
+ + SAML
+ + "SubjectConfirmation/"
+ + SAML
+ + "SubjectConfirmationData";
+/** Xpath expression to the PersonData:Person element */
+ private static final String PERSON_XPATH =
+ SAML_SUBJECT_CONFIRMATION_DATA_XPATH + "/" + PDATA + "Person";
+ /** Xpath expression to the SAML:Attribute element */
+ private static final String ATTRIBUTE_XPATH =
+ ROOT + SAML + "AttributeStatement/" + SAML + "Attribute";
+ /** Xpath expression to the SAML:AttributeName attribute */
+ private static final String ATTRIBUTE_NAME_XPATH =
+ ROOT + SAML + "AttributeStatement/" + SAML + "Attribute/@AttributeName";
+ /** Xpath expression to the SAML:AttributeNamespace attribute */
+ private static final String ATTRIBUTE_NAMESPACE_XPATH =
+ ROOT
+ + SAML
+ + "AttributeStatement/"
+ + SAML
+ + "Attribute/@AttributeNamespace";
+ /** Xpath expression to the SAML:AttributeValue element */
+ private static final String ATTRIBUTE_VALUE_XPATH =
+ ROOT
+ + SAML
+ + "AttributeStatement/"
+ + SAML
+ + "Attribute/"
+ + SAML
+ + "AttributeValue";
+
+ /** Singleton instance. <code>null</code>, if none has been created. */
+ private static IdentityLinkValidator instance;
+
+ /**
+ * Constructor for a singleton IdentityLinkValidator.
+ * @return a new IdentityLinkValidator instance
+ * @throws ValidateException if no instance can be created
+ */
+ public static synchronized IdentityLinkValidator getInstance()
+ throws ValidateException {
+ if (instance == null) {
+ instance = new IdentityLinkValidator();
+ }
+ return instance;
+ }
+
+ /**
+ * Method validate. Validates the {@link IdentityLink}
+ * @param identityLink The identityLink to validate
+ * @throws ValidateException on any validation error
+ */
+ public void validate(IdentityLink identityLink) throws ValidateException {
+
+ //Search the SAML:ASSERTION Object (A2.054)
+ if (identityLink.getSamlAssertion() == null)
+ throw new ValidateException("validator.00", null);
+
+ // Check how many saml:Assertion/saml:AttributeStatement/
+ // saml:Subject/ saml:SubjectConfirmation/
+ // saml:SubjectConfirmationData/pr:Person of type
+ // PhysicalPersonType exist (A2.056)
+ NodeList nl =
+ XPathUtils.selectNodeList(identityLink.getSamlAssertion(), PERSON_XPATH);
+ // If we have just one Person-Element we don't need to check the attributes
+ int counterPhysicalPersonType = 0;
+ if (nl.getLength() > 1)
+ for (int i = 0; i < nl.getLength(); i++) {
+ String xsiType =
+ ((Element) nl.item(i))
+ .getAttributeNodeNS(
+ "http://www.w3.org/2001/XMLSchema-instance",
+ "type")
+ .getNodeValue();
+ // We have to check if xsiType contains "PhysicalPersonType"
+ // An equal-check will fail because of the Namespace-prefix of the attribute value
+ if (xsiType.indexOf("PhysicalPersonType") > -1)
+ counterPhysicalPersonType++;
+ }
+ if (counterPhysicalPersonType > 1)
+ throw new ValidateException("validator.01", null);
+
+ //Check the SAML:ATTRIBUTES
+ nl = XPathUtils.selectNodeList(identityLink.getSamlAssertion(), ATTRIBUTE_XPATH);
+ for (int i = 0; i < nl.getLength(); i++) {
+ String attributeName =
+ XPathUtils.getAttributeValue(
+ (Element) nl.item(i),
+ "@AttributeName",
+ null);
+ String attributeNS =
+ XPathUtils.getAttributeValue(
+ (Element) nl.item(i),
+ "@AttributeNamespace",
+ null);
+ if (attributeName.equals("CitizenPublicKey")) {
+ if (attributeNS.equals("http://www.buergerkarte.at/namespaces/personenbindung/20020506#")) {
+ Element attributeValue =
+ (Element) XPathUtils.selectSingleNode((Element) nl.item(i),SAML + "AttributeValue/" + DSIG + "RSAKeyValue");
+ if (attributeValue==null)
+ attributeValue =
+ (Element) XPathUtils.selectSingleNode((Element)nl.item(i), SAML + "AttributeValue/" + ECDSA + "ECDSAKeyValue");
+ if (attributeValue == null)
+ throw new ValidateException("validator.02", null);
+ }
+ else
+ throw new ValidateException("validator.03", null);
+ }
+ else
+ throw new ValidateException("validator.04", null);
+ }
+
+ //Check if dsig:Signature exists
+ Element dsigSignature = (Element) XPathUtils.selectSingleNode(identityLink.getSamlAssertion(),ROOT + DSIG + "Signature");
+ if (dsigSignature==null) throw new ValidateException("validator.05", null);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/validator/ValidateException.java b/id.server/src/at/gv/egovernment/moa/id/auth/validator/ValidateException.java
new file mode 100644
index 000000000..a6685fca8
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/validator/ValidateException.java
@@ -0,0 +1,35 @@
+package at.gv.egovernment.moa.id.auth.validator;
+
+import at.gv.egovernment.moa.id.MOAIDException;
+
+/**
+ * Exception thrown while validating an incoming XML structure
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ValidateException extends MOAIDException {
+
+ /**
+ * Constructor for ValidateException.
+ * @param messageId
+ * @param parameters
+ */
+ public ValidateException(String messageId, Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+ /**
+ * Constructor for ValidateException.
+ * @param messageId
+ * @param parameters
+ * @param wrapped
+ */
+ public ValidateException(
+ String messageId,
+ Object[] parameters,
+ Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/validator/VerifyXMLSignatureResponseValidator.java b/id.server/src/at/gv/egovernment/moa/id/auth/validator/VerifyXMLSignatureResponseValidator.java
new file mode 100644
index 000000000..a238d28cb
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/validator/VerifyXMLSignatureResponseValidator.java
@@ -0,0 +1,124 @@
+package at.gv.egovernment.moa.id.auth.validator;
+
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+
+import iaik.asn1.structures.Name;
+import iaik.utils.RFC2253NameParserException;
+import iaik.x509.X509Certificate;
+
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse;
+
+/**
+ * This class is used to validate an {@link VerifyXMLSignatureResponse}
+ * returned by MOA-SPSS
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class VerifyXMLSignatureResponseValidator {
+
+ /** Identification string for checking identity link */
+ public static final String CHECK_IDENTITY_LINK = "IdentityLink";
+ /** Identification string for checking authentication block */
+ public static final String CHECK_AUTH_BLOCK = "AuthBlock";
+
+ /** Singleton instance. <code>null</code>, if none has been created. */
+ private static VerifyXMLSignatureResponseValidator instance;
+
+ /**
+ * Constructor for a singleton VerifyXMLSignatureResponseValidator.
+ */
+ public static synchronized VerifyXMLSignatureResponseValidator getInstance()
+ throws ValidateException {
+ if (instance == null) {
+ instance = new VerifyXMLSignatureResponseValidator();
+ }
+ return instance;
+ }
+
+ /**
+ * Validates a {@link VerifyXMLSignatureResponse} returned by MOA-SPSS.
+ *
+ * @param verifyXMLSignatureResponse the <code>&lt;VerifyXMLSignatureResponse&gt;</code>
+ * @param identityLinkSignersSubjectDNNames subject names configured
+ * @param whatToCheck is used to identify whether the identityLink or the Auth-Block is validated
+ * @throws ValidateException on any validation error
+ */
+ public void validate(
+ VerifyXMLSignatureResponse verifyXMLSignatureResponse,
+ String[] identityLinkSignersSubjectDNNames, String whatToCheck)
+ throws ValidateException {
+
+ if (verifyXMLSignatureResponse.getSignatureCheckCode() != 0)
+ throw new ValidateException("validator.06", null);
+ if (verifyXMLSignatureResponse.getCertificateCheckCode() != 0)
+ if (whatToCheck.equals(CHECK_IDENTITY_LINK))
+ throw new ValidateException("validator.07", null);
+ else
+ throw new ValidateException("validator.19", null);
+ if (verifyXMLSignatureResponse.isXmlDSIGManigest())
+ if (verifyXMLSignatureResponse.getXmlDSIGManifestCheckCode() != 0)
+ throw new ValidateException("validator.08", null);
+ //Check whether the returned X509 SubjectName is in the MOA-ID configuration or not
+ if (identityLinkSignersSubjectDNNames != null) {
+ String subjectDN = "";
+ X509Certificate x509Cert = verifyXMLSignatureResponse.getX509certificate();
+ try {
+ subjectDN = ((Name) x509Cert.getSubjectDN()).getRFC2253String();
+ }
+ catch (RFC2253NameParserException e) {
+ throw new ValidateException("validator.17", null);
+ }
+ boolean found = false;
+ for (int i = 0; i < identityLinkSignersSubjectDNNames.length; i++) {
+ if (identityLinkSignersSubjectDNNames[i].equals(subjectDN))
+ found = true;
+ }
+ if (!found)
+ throw new ValidateException(
+ "validator.18",
+ new Object[] { subjectDN });
+ }
+ }
+
+ /**
+ * Method validateCertificate.
+ * @param vsr is the VerifyXMLSignatureResponse
+ * @param idl
+ * @throws ValidateException
+ */
+ public void validateCertificate(
+ VerifyXMLSignatureResponse verifyXMLSignatureResponse,
+ IdentityLink idl)
+ throws ValidateException {
+
+ X509Certificate x509Response = verifyXMLSignatureResponse.getX509certificate();
+ PublicKey[] pubKeysIdentityLink = (PublicKey[]) idl.getPublicKey();
+
+ RSAPublicKey pubKeyResponse = (RSAPublicKey) x509Response.getPublicKey();
+
+ boolean found = false;
+ for (int i = 0; i < pubKeysIdentityLink.length; i++) {
+ if (idl.getPublicKey()[i]
+ instanceof java.security.interfaces.RSAPublicKey) {
+ /* for (int j = 0;
+ j < idl.getPublicKey()[i].getClass().getInterfaces().length;
+ j++) {
+ if (idl.getPublicKey()[i].getClass().getInterfaces()[j].getName()
+ .equals("java.security.interfaces.RSAPublicKey")) {*/
+ RSAPublicKey rsakey = (RSAPublicKey) pubKeysIdentityLink[i];
+ if (rsakey.getModulus().equals(pubKeyResponse.getModulus())
+ && rsakey.getPublicExponent().equals(
+ pubKeyResponse.getPublicExponent()))
+ found = true;
+ }
+
+ }
+
+ if (!found)
+ throw new ValidateException("validator.09", null);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/config/ConfigurationBuilder.java b/id.server/src/at/gv/egovernment/moa/id/config/ConfigurationBuilder.java
new file mode 100644
index 000000000..f91222ac3
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/config/ConfigurationBuilder.java
@@ -0,0 +1,678 @@
+package at.gv.egovernment.moa.id.config;
+
+import iaik.pki.pathvalidation.ChainingModes;
+import iaik.utils.RFC2253NameParser;
+import iaik.utils.RFC2253NameParserException;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.traversal.NodeIterator;
+
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.config.proxy.OAConfiguration;
+import at.gv.egovernment.moa.id.config.proxy.OAProxyParameter;
+import at.gv.egovernment.moa.id.data.IssuerAndSerial;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.BoolUtils;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.FileUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * A class that builds configuration data from a DOM based representation.
+ *
+ * @author Patrick Peck
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class ConfigurationBuilder {
+
+ //
+ // XPath namespace prefix shortcuts
+ //
+ /** an XPATH-Expression */
+ private static final String CONF = Constants.MOA_ID_CONFIG_PREFIX + ":";
+ /** an XPATH-Expression */
+ private static final String DSIG = Constants.DSIG_PREFIX + ":";
+
+ //
+ // chaining mode constants appearing in the configuration file
+ //
+ /** an XPATH-Expression */
+ private static final String CM_CHAINING = "chaining";
+ /** an XPATH-Expression */
+ private static final String CM_PKIX = "pkix";
+ /** an XPATH-Expression */
+ private static final String DEFAULT_ENCODING = "UTF-8";
+
+ /**
+ * Default online application configuration file name
+ * (used when <code>/OnlineApplication/ProxyComponent@configFileURL</code> is <code>null</code>).
+ */
+ public static final String DEFAULT_OA_CONFIG_FILENAME = "MOAConfig.xml";
+
+ //
+ // XPath expressions to select certain parts of the configuration
+ //
+ /** an XPATH-Expression */
+ private static final String ROOT = "/" + CONF + "MOA-IDConfiguration/";
+ /** an XPATH-Expression */
+ private static final String ROOTOA = "/" + CONF + "Configuration/";
+ /** an XPATH-Expression */
+ private static final String AUTH_BKU_XPATH =
+ ROOT + CONF + "AuthComponent/" + CONF + "BKUSelection";
+ /** an XPATH-Expression */
+ private static final String AUTH_SECLAYER_TRANSFORMS_INFO_FILENAME_XPATH =
+ ROOT + CONF + "AuthComponent/" + CONF + "SecurityLayer/" + CONF + "TransformsInfo/@filename";
+ /** an XPATH-Expression */
+ private static final String AUTH_MOA_SP_XPATH =
+ ROOT + CONF + "AuthComponent/" + CONF + "MOA-SP";
+ /** an XPATH-Expression */
+ private static final String AUTH_MOA_SP_VERIFY_IDENTITY_TRUST_ID_XPATH =
+ ROOT + CONF + "AuthComponent/" + CONF + "MOA-SP/" + CONF + "VerifyIdentityLink/" + CONF + "TrustProfileID";
+ /** an XPATH-Expression */
+ private static final String AUTH_MOA_SP_VERIFY_AUTH_TRUST_ID_XPATH =
+ ROOT + CONF + "AuthComponent/" + CONF + "MOA-SP/" + CONF + "VerifyAuthBlock/" + CONF + "TrustProfileID";
+ /** an XPATH-Expression */
+ private static final String AUTH_MOA_SP_VERIFY_AUTH_VERIFY_ID_XPATH =
+ ROOT + CONF + "AuthComponent/" + CONF + "MOA-SP/" + CONF + "VerifyAuthBlock/" + CONF + "VerifyTransformsInfoProfileID";
+
+ /** an XPATH-Expression */
+ private static final String AUTH_IDENTITY_LINK_X509SUBJECTNAME_XPATH =
+ ROOT + CONF + "AuthComponent/" + CONF + "IdentityLinkSigners/" + CONF + "X509SubjectName";
+ /** an XPATH-Expression */
+ private static final String PROXY_AUTH_XPATH =
+ ROOT + CONF + "ProxyComponent/" + CONF + "AuthComponent";
+
+ /** an XPATH-Expression */
+ private static final String OA_XPATH = ROOT + CONF + "OnlineApplication";
+ /** an XPATH-Expression */
+ private static final String OA_LOGIN_XPATH = ROOT + CONF + "OnlineApplication/@loginURL";
+ /** an XPATH-Expression */
+ private static final String OA_AUTH_COMPONENT_XPATH = CONF + "AuthComponent";
+ /** an XPATH-Expression */
+ private static final String OA_PROXY_COMPONENT_XPATH = CONF + "ProxyComponent";
+ /** an XPATH-Expression */
+ private static final String OA_PROXY_COMPONENT_ABSOLUTE_XPATH = ROOT + CONF + "OnlineApplication/" + CONF + "ProxyComponent";
+ /** an XPATH-Expression */
+ private static final String OA_PROXY_URL_XPATH = CONF + "ProxyComponent/@configFileURL";
+ /** an XPATH-Expression */
+ private static final String OA_PROXY_SESSION_TIMEOUT_XPATH = CONF + "ProxyComponent/@sessionTimeOut";
+ /** an XPATH-Expression */
+ private static final String OA_PROXY_LOGIN_PARA_XPATH = CONF + "ProxyComponent/@loginParameterResolverImpl";
+ /** an XPATH-Expression */
+ private static final String OA_PROXY_CONNECTION_BUILDER_XPATH = CONF + "ProxyComponent/@connectionBuilderImpl";
+ /** an XPATH-Expression */
+ private static final String CONNECTION_PARAMETER_URL_XPATH =
+ CONF + "ConnectionParameter/@URL";
+ /** an XPATH-Expression */
+ private static final String CONNECTION_PARAMETER_ACCEPTED_CERTS_XPATH =
+ CONF + "ConnectionParameter/" + CONF + "AcceptedServerCertificates";
+ /** an XPATH-Expression */
+ private static final String CONNECTION_PARAMETERN_KEYSTORE_XPATH =
+ CONF + "ConnectionParameter/" + CONF + "ClientKeyStore";
+ /** an XPATH-Expression */
+ private static final String CONNECTION_PARAMETER_KEYSTORE_PASS_XPATH =
+ CONNECTION_PARAMETERN_KEYSTORE_XPATH + "/@password";
+ /** an XPATH-Expression */
+ private static final String GENERIC_CONFIGURATION_XPATH =
+ ROOT + CONF + "GenericConfiguration";
+ /** an XPATH-Expression */
+ private static final String OACONF_LOGIN_TYPE_XPATH =
+ ROOTOA + CONF + "LoginType";
+ /** an XPATH-Expression */
+ private static final String OACONF_PARAM_AUTH_PARAMETER_XPATH =
+ ROOTOA + CONF + "ParamAuth/" + CONF + "Parameter";
+ /** an XPATH-Expression */
+ private static final String OACONF_USER_ID_XPATH =
+ ROOTOA + CONF + "BasicAuth/" + CONF + "UserID";
+ /** an XPATH-Expression */
+ private static final String OACONF_PASSWORD_XPATH =
+ ROOTOA + CONF + "BasicAuth/" + CONF + "Password";
+ /** an XPATH-Expression */
+ private static final String OACONF_HEADER_AUTH_HEADER_XPATH =
+ ROOTOA + CONF + "HeaderAuth/" + CONF + "Header";
+ /** an XPATH-Expression */
+ private static final String CHAINING_MODES_XPATH =
+ ROOT + CONF + "ChainingModes";
+ /** an XPATH-Expression */
+ private static final String CHAINING_MODES_DEFAULT_XPATH =
+ CHAINING_MODES_XPATH + "/@systemDefaultMode";
+ /** an XPATH-Expression */
+ private static final String TRUST_ANCHOR_XPATH =
+ ROOT + CONF + "ChainingModes/" + CONF + "TrustAnchor";
+ /** an XPATH-Expression */
+ private static final String ISSUER_XPATH = DSIG + "X509IssuerName";
+ /** an XPATH-Expression */
+ private static final String SERIAL_XPATH = DSIG + "X509SerialNumber";
+ /** an XPATH-Expression */
+ private static final String TRUSTED_CA_CERTIFICATES_XPATH =
+ ROOT + CONF + "TrustedCACertificates";
+
+ /** The root element of the MOA-ID configuration */
+ private Element configElem;
+
+ /**
+ * Creates a new <code>MOAConfigurationProvider</code>.
+ *
+ * @param configElem The root element of the MOA-ID configuration.
+ */
+ public ConfigurationBuilder(Element configElem) {
+ this.configElem = configElem;
+ }
+
+ /**
+ * Returns the root element of the MOA-ID configuration.
+ *
+ * @return The root element of the MOA-ID configuration.
+ */
+ public Element getConfigElem() {
+ return configElem;
+ }
+
+ /**
+ * Build a ConnectionParameter object containing all information
+ * of the moa-sp element in the authentication component
+ * @return ConnectionParameter of the authentication component moa-sp element
+ */
+ public ConnectionParameter buildAuthBKUConnectionParameter() {
+
+ Element authBKU = (Element) XPathUtils.selectSingleNode(getConfigElem(), AUTH_BKU_XPATH);
+ if (authBKU==null) return null;
+ return buildConnectionParameter(authBKU);
+ }
+
+ /**
+ * Method buildAuthBKUSelectionType.
+ *
+ * Build a string with the configuration value of BKUSelectionAlternative
+ *
+ * @return String
+ */
+ public String buildAuthBKUSelectionType() {
+
+ Element authBKU = (Element) XPathUtils.selectSingleNode(getConfigElem(), AUTH_BKU_XPATH);
+ if (authBKU==null) return null;
+ return (authBKU).getAttribute("BKUSelectionAlternative");
+ }
+
+ /**
+ * Build a string array with all filenames leading
+ * to the Transforms Information for the Security Layer
+ * @return String[] of filenames to the Security Layer Transforms Information
+ */
+ public String[] buildTransformsInfoFileNames() {
+
+ List transformsInfoFileNames = new ArrayList();
+ NodeIterator tiIter =
+ XPathUtils.selectNodeIterator(
+ getConfigElem(),
+ AUTH_SECLAYER_TRANSFORMS_INFO_FILENAME_XPATH);
+ Attr tiElem;
+
+ while ((tiElem = (Attr) tiIter.nextNode()) != null) {
+
+ String tiFileName = tiElem.getNodeValue();
+ transformsInfoFileNames.add(tiFileName);
+ }
+ String[] result = new String[transformsInfoFileNames.size()];
+ transformsInfoFileNames.toArray(result);
+
+ return result;
+ }
+
+ /**
+ * Build a ConnectionParameter bean containing all information
+ * of the authentication component moa-sp element
+ * @return ConnectionParameter of the authentication component moa-sp element
+ */
+ public ConnectionParameter buildMoaSpConnectionParameter() {
+
+ Element connectionParameter = (Element) XPathUtils.selectSingleNode(getConfigElem(), AUTH_MOA_SP_XPATH);
+ if (connectionParameter==null) return null;
+ return buildConnectionParameter(connectionParameter);
+ }
+
+ /**
+ * Return a string with a url-reference to the VerifyIdentityLink trust
+ * profile id within the moa-sp part of the authentication component
+ * @return String with a url-reference to the VerifyIdentityLink trust profile ID
+ */
+ public String getMoaSpIdentityLinkTrustProfileID() {
+ return XPathUtils.getElementValue(
+ getConfigElem(),
+ AUTH_MOA_SP_VERIFY_IDENTITY_TRUST_ID_XPATH,
+ "");
+ }
+ /**
+ * Return a string representation of an URL pointing to trusted CA Certificates
+ * @return String representation of an URL pointing to trusted CA Certificates
+ */
+ public String getTrustedCACertificates() {
+ return XPathUtils.getElementValue(
+ getConfigElem(),
+ TRUSTED_CA_CERTIFICATES_XPATH,null);
+ }
+
+ /**
+ * Return a string with a url-reference to the VerifyAuthBlock trust
+ * profile id within the moa-sp part of the authentication component
+ * @return String with a url-reference to the VerifyAuthBlock trust profile ID
+ */
+ public String getMoaSpAuthBlockTrustProfileID() {
+ return XPathUtils.getElementValue(
+ getConfigElem(),
+ AUTH_MOA_SP_VERIFY_AUTH_TRUST_ID_XPATH,
+ "");
+ }
+ /**
+ * Build a string array with references to all verify transform info
+ * IDs within the moa-sp part of the authentication component
+ * @return A string array containing all urls to the
+ * verify transform info IDs
+ */
+ public String[] buildMoaSpAuthBlockVerifyTransformsInfoIDs() {
+
+ List verifyTransformsInfoIDs = new ArrayList();
+ NodeIterator vtIter =
+ XPathUtils.selectNodeIterator(
+ getConfigElem(),
+ AUTH_MOA_SP_VERIFY_AUTH_VERIFY_ID_XPATH);
+ Element vtElem;
+
+ while ((vtElem = (Element) vtIter.nextNode()) != null) {
+
+ String vtInfoIDs = DOMUtils.getText(vtElem);
+ verifyTransformsInfoIDs.add(vtInfoIDs);
+ }
+ String[] result = new String[verifyTransformsInfoIDs.size()];
+ verifyTransformsInfoIDs.toArray(result);
+
+ return result;
+ }
+
+ /**
+ * Return a string array containing all X509 Subject Names
+ * of the Identity Link Signers
+ * @return String with a url-reference to the VerifyAuthBlock trust profile ID
+ */
+ public String[] getIdentityLink_X509SubjectNames() {
+
+ List x509SubjectNameList = new ArrayList();
+ NodeIterator x509Iter =
+ XPathUtils.selectNodeIterator(
+ getConfigElem(),
+ AUTH_IDENTITY_LINK_X509SUBJECTNAME_XPATH);
+ Element x509Elem;
+
+ while ((x509Elem = (Element) x509Iter.nextNode()) != null) {
+
+ String vtInfoIDs = DOMUtils.getText(x509Elem);
+ x509SubjectNameList.add(vtInfoIDs);
+ }
+ String[] result = new String[x509SubjectNameList.size()];
+ x509SubjectNameList.toArray(result);
+
+ return result;
+ }
+
+ /**
+ * Build an array of the OnlineApplication Parameters containing information
+ * about the authentication component
+ * @return An OAProxyParameter array containing beans
+ * with all relevant information for the authentication component of the online
+ * application
+ */
+ public OAAuthParameter[] buildOnlineApplicationAuthParameters() {
+
+ List OA_set = new ArrayList();
+ NodeList OAIter = XPathUtils.selectNodeList(getConfigElem(), OA_XPATH);
+
+ for (int i = 0; i < OAIter.getLength(); i++) {
+ Element oAElem = (Element) OAIter.item(i);
+ Element authComponent =
+ (Element) XPathUtils.selectSingleNode(oAElem, OA_AUTH_COMPONENT_XPATH);
+
+ OAAuthParameter oap = new OAAuthParameter();
+ oap.setPublicURLPrefix(oAElem.getAttribute("publicURLPrefix"));
+ //Check if there is an Auth-Block to read from configuration
+ if (authComponent!=null)
+ {
+ oap.setProvideZMRZahl(BoolUtils.valueOf(authComponent.getAttribute("provideZMRZahl")));
+ oap.setProvideAuthBlock(BoolUtils.valueOf(authComponent.getAttribute("provideAUTHBlock")));
+ oap.setProvideIdentityLink(BoolUtils.valueOf(authComponent.getAttribute("provideIdentityLink")));
+ }
+ OA_set.add(oap);
+ }
+ OAAuthParameter[] result =
+ new OAAuthParameter[OA_set.size()];
+ OA_set.toArray(result);
+
+ return result;
+
+ }
+
+ /**
+ * Build a bean containing all information about the ProxyComponent
+ * @return The ConnectionParameter for the Proxy Component
+ */
+ public ConnectionParameter buildAuthComponentConnectionParameter()
+ {
+
+ Element connectionParameter = (Element) XPathUtils.selectSingleNode(getConfigElem(), PROXY_AUTH_XPATH);
+ if (connectionParameter==null) return null;
+ return buildConnectionParameter(connectionParameter);
+
+ }
+ /**
+ * Method buildConnectionParameter: internal Method for creating a
+ * ConnectionParameter object with all data found in the incoming element
+ * @param root: this Element contains the ConnectionParameter
+ * @return ConnectionParameter
+ */
+ protected ConnectionParameter buildConnectionParameter(Element root)
+ {
+ ConnectionParameter result = new ConnectionParameter();
+ result.setAcceptedServerCertificates(
+ XPathUtils.getElementValue(root,CONNECTION_PARAMETER_ACCEPTED_CERTS_XPATH,null));
+ result.setUrl(
+ XPathUtils.getAttributeValue(root, CONNECTION_PARAMETER_URL_XPATH, ""));
+ result.setClientKeyStore(
+ XPathUtils.getElementValue(root,CONNECTION_PARAMETERN_KEYSTORE_XPATH,null));
+ result.setClientKeyStorePassword(
+ XPathUtils.getAttributeValue(root,CONNECTION_PARAMETER_KEYSTORE_PASS_XPATH,""));
+
+ if ((result.getAcceptedServerCertificates()==null)
+ && (result.getUrl()=="")
+ && (result.getClientKeyStore()==null)
+ && (result.getClientKeyStorePassword()==""))
+ return null;
+
+ return result;
+ }
+
+ /**
+ * Build an array of OnlineApplication Parameter Beans containing information
+ * about the proxy component
+ * @return An OAProxyParameter array containing beans
+ * with all relevant information for the proxy component of the online
+ * application
+ */
+ public OAProxyParameter[] buildOnlineApplicationProxyParameters() throws ConfigurationException{
+
+ List oA_list = new ArrayList();
+ NodeList OAIter = XPathUtils.selectNodeList(getConfigElem(), OA_XPATH);
+
+ for (int i = 0; i < OAIter.getLength(); i++) {
+ Element oAElem = (Element) OAIter.item(i);
+ OAProxyParameter oap = new OAProxyParameter();
+
+ oap.setPublicURLPrefix(oAElem.getAttribute("publicURLPrefix"));
+ Element proxyComponentElem = (Element) XPathUtils.selectSingleNode(oAElem,OA_PROXY_COMPONENT_XPATH);
+ if (proxyComponentElem != null) {
+ oap.setConfigFileURL(XPathUtils.getAttributeValue(oAElem, OA_PROXY_URL_XPATH, null));
+ // default session time out: 3600 sec = 1 h
+ oap.setSessionTimeOut(new Integer(XPathUtils.getAttributeValue(oAElem,OA_PROXY_SESSION_TIMEOUT_XPATH,"3600")).intValue());
+ oap.setLoginParameterResolverImpl(XPathUtils.getAttributeValue(oAElem, OA_PROXY_LOGIN_PARA_XPATH, null));
+ oap.setConnectionBuilderImpl(XPathUtils.getAttributeValue(oAElem,OA_PROXY_CONNECTION_BUILDER_XPATH, null));
+
+ ConnectionParameter conPara = buildConnectionParameter(proxyComponentElem);
+ oap.setConnectionParameter(conPara);
+
+ OAConfiguration oaConf = buildOAConfiguration(getOAConfigElement(oap));
+ oap.setOaConfiguration(oaConf);
+
+ oA_list.add(oap);
+ }
+ }
+ OAProxyParameter[] result =
+ new OAProxyParameter[oA_list.size()];
+ oA_list.toArray(result);
+
+ return result;
+
+ }
+
+ /**
+ * Build the mapping of generic configuration properties.
+ *
+ * @return a {@link Map} of generic configuration properties (a name to value
+ * mapping) from the configuration.
+ */
+ public Map buildGenericConfiguration() {
+
+ Map genericConfiguration = new HashMap();
+ NodeIterator gcIter =
+ XPathUtils.selectNodeIterator(
+ getConfigElem(),
+ GENERIC_CONFIGURATION_XPATH);
+ Element gcElem;
+
+ while ((gcElem = (Element) gcIter.nextNode()) != null) {
+ String gcName = gcElem.getAttribute("name");
+ String gcValue = gcElem.getAttribute("value");
+
+ genericConfiguration.put(gcName, gcValue);
+ }
+
+ return genericConfiguration;
+ }
+ /**
+ * Method buildOAConfiguration.
+ *
+ * Build an {@link OAConfiguration} Object from the given configuration DOM element
+ *
+ * @param root
+ * @return OAConfiguration
+ * @throws ConfigurationException
+ */
+ public OAConfiguration buildOAConfiguration(Element root) throws ConfigurationException{
+
+ OAConfiguration oaConfiguration = new OAConfiguration();
+
+ //The LoginType hast to be "stateless" or "stateful" to be valid
+ oaConfiguration.setLoginType(
+ XPathUtils.getElementValue(root, OACONF_LOGIN_TYPE_XPATH, null));
+
+ //Try to build the Parameter Auth Parameters
+ NodeIterator paramAuthIter =
+ XPathUtils.selectNodeIterator(
+ root,
+ OACONF_PARAM_AUTH_PARAMETER_XPATH);
+ Element paramAuthElem;
+ HashMap paramAuthMap = new HashMap();
+ while ((paramAuthElem = (Element) paramAuthIter.nextNode()) != null) {
+ String name = XPathUtils.getAttributeValue(paramAuthElem, "@Name", null);
+ String value = XPathUtils.getAttributeValue(paramAuthElem, "@Value", null);
+ if (paramAuthMap.containsKey(name))
+ throw new ConfigurationException("config.06", new Object[]{"Doppelter Wert für Parameter per HeaderAuthentication"});
+ paramAuthMap.put(name, value);
+ }
+ oaConfiguration.setParamAuthMapping(paramAuthMap);
+ // Try to build the BasicAuthParameters
+ oaConfiguration.setBasicAuthUserIDMapping(
+ XPathUtils.getElementValue(root, OACONF_USER_ID_XPATH, null));
+ oaConfiguration.setBasicAuthPasswordMapping(
+ XPathUtils.getElementValue(root, OACONF_PASSWORD_XPATH, null));
+
+ //Try to build the Parameter Auth Parameters
+ NodeIterator headerAuthIter = XPathUtils.selectNodeIterator(root,OACONF_HEADER_AUTH_HEADER_XPATH);
+
+ Element headerAuthElem;
+ HashMap headerAuthMap = new HashMap();
+ while ((headerAuthElem = (Element) headerAuthIter.nextNode()) != null) {
+ String name =
+ XPathUtils.getAttributeValue(headerAuthElem, "@Name", null);
+ String value =
+ XPathUtils.getAttributeValue(headerAuthElem, "@Value", null);
+ // Contains Key (Neue Config-Exception: doppelte werte)
+ if (headerAuthMap.containsKey(name))
+ throw new ConfigurationException("config.06", new Object[]{"Doppelter Wert für Parameter per HeaderAuthentication"});
+ headerAuthMap.put(name, value);
+ }
+ oaConfiguration.setHeaderAuthMapping(headerAuthMap);
+
+ if (paramAuthMap.size() == 0) {
+ if (oaConfiguration.getBasicAuthUserIDMapping() == null) {
+ oaConfiguration.setAuthType(OAConfiguration.HEADER_AUTH);
+ }
+ else
+ oaConfiguration.setAuthType(OAConfiguration.BASIC_AUTH);
+ }
+ else
+ oaConfiguration.setAuthType(OAConfiguration.PARAM_AUTH);
+
+ return oaConfiguration;
+ }
+
+ /**
+ * Reads the configuration file of the online application, and creates a DOM tree from it.
+ * If <code>/OnlineApplication/ProxyComponent@configFileURL</code> is not given,
+ * uses default configuration file location.
+ *
+ * @param oap configuration data of online application, meant for use by MOA-ID-PROXY
+ * @return Element DOM tree root element
+ * @throws ConfigurationException on any exception thrown
+ */
+ private Element getOAConfigElement(OAProxyParameter oap) throws ConfigurationException
+ {
+ try {
+ String configFileURL = oap.getConfigFileURL();
+ if (configFileURL == null) {
+ // use default config file URL, when config file URL is not given
+ configFileURL = oap.getConnectionParameter().getUrl();
+ if (configFileURL.charAt(configFileURL.length() - 1) != '/')
+ configFileURL += "/";
+ configFileURL += DEFAULT_OA_CONFIG_FILENAME;
+ }
+ Logger.info("Loading MOA-OA configuration " + configFileURL);
+ Element configElem = DOMUtils.parseXmlValidating(
+ new ByteArrayInputStream(FileUtils.readURL(configFileURL)));
+ return configElem;
+ }
+ catch (Throwable t) {
+ throw new ConfigurationException("config.03", new Object[] {"OAConfiguration"} , t);
+ }
+ }
+
+ /**
+ * Returns the default chaining mode from the configuration.
+ *
+ * @return The default chaining mode.
+ */
+ public String getDefaultChainingMode() {
+ String defaultChaining =
+ XPathUtils.getAttributeValue(
+ getConfigElem(),
+ CHAINING_MODES_DEFAULT_XPATH,
+ CM_CHAINING);
+
+ return translateChainingMode(defaultChaining);
+
+ }
+ /**
+ * Build the chaining modes for all configured trust anchors.
+ *
+ * @return The mapping from trust anchors to chaining modes.
+ */
+ public Map buildChainingModes() {
+ Map chainingModes = new HashMap();
+ NodeIterator trustIter =
+ XPathUtils.selectNodeIterator(getConfigElem(), TRUST_ANCHOR_XPATH);
+ Element trustAnchorElem;
+
+ while ((trustAnchorElem = (Element) trustIter.nextNode()) != null) {
+ IssuerAndSerial issuerAndSerial = buildIssuerAndSerial(trustAnchorElem);
+ String mode = trustAnchorElem.getAttribute("mode");
+
+ if (issuerAndSerial != null) {
+ chainingModes.put(issuerAndSerial, translateChainingMode(mode));
+ }
+ }
+
+ return chainingModes;
+ }
+
+ /**
+ * Build an <code>IssuerAndSerial</code> from the DOM representation.
+ *
+ * @param root The root element (being of type <code>dsig:
+ * X509IssuerSerialType</code>.
+ * @return The issuer and serial number contained in the <code>root</code>
+ * element or <code>null</code> if could not be built for any reason.
+ */
+ private IssuerAndSerial buildIssuerAndSerial(Element root) {
+ String issuer = XPathUtils.getElementValue(root, ISSUER_XPATH, null);
+ String serial = XPathUtils.getElementValue(root, SERIAL_XPATH, null);
+
+ if (issuer != null && serial != null) {
+ try {
+ RFC2253NameParser nameParser = new RFC2253NameParser(issuer);
+ Principal issuerDN = nameParser.parse();
+
+ return new IssuerAndSerial(issuerDN, new BigInteger(serial));
+ } catch (RFC2253NameParserException e) {
+ warn("config.09", new Object[] { issuer, serial }, e);
+ return null;
+ } catch (NumberFormatException e) {
+ warn("config.09", new Object[] { issuer, serial }, e);
+ return null;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Translate the chaining mode from the configuration file to one used in the
+ * IAIK MOA API.
+ *
+ * @param chainingMode The chaining mode from the configuration.
+ * @return The chaining mode as provided by the <code>ChainingModes</code>
+ * interface.
+ * @see iaik.pki.pathvalidation.ChainingModes
+ */
+ private String translateChainingMode(String chainingMode) {
+ if (chainingMode.equals(CM_CHAINING)) {
+ return ChainingModes.CHAIN_MODE;
+ } else if (chainingMode.equals(CM_PKIX)) {
+ return ChainingModes.PKIX_MODE;
+ } else {
+ return ChainingModes.CHAIN_MODE;
+ }
+ }
+
+ /**
+ * Method warn.
+ * @param messageId to identify a country-specific message
+ * @param parameters for the logger
+ */
+ //
+ // various utility methods
+ //
+
+ private static void warn(String messageId, Object[] parameters) {
+ Logger.warn(MOAIDMessageProvider.getInstance().getMessage(messageId, parameters));
+ }
+
+ /**
+ * Method warn.
+ * @param messageId to identify a country-specific message
+ * @param args for the logger
+ * @param t as throwabl
+ */
+ private static void warn(String messageId, Object[] args, Throwable t) {
+ Logger.warn(MOAIDMessageProvider.getInstance().getMessage(messageId, args), t);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/config/ConfigurationException.java b/id.server/src/at/gv/egovernment/moa/id/config/ConfigurationException.java
new file mode 100644
index 000000000..2ebec0398
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/config/ConfigurationException.java
@@ -0,0 +1,31 @@
+package at.gv.egovernment.moa.id.config;
+
+import at.gv.egovernment.moa.id.MOAIDException;
+
+/**
+ * Exception signalling an error in the configuration.
+ *
+ * @author Patrick Peck
+ * @version $Id$
+ */
+public class ConfigurationException extends MOAIDException {
+
+ /**
+ * Create a <code>MOAConfigurationException</code>.
+ */
+ public ConfigurationException(String messageId, Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+ /**
+ * Create a <code>MOAConfigurationException</code>.
+ */
+ public ConfigurationException(
+ String messageId,
+ Object[] parameters,
+ Throwable wrapped) {
+
+ super(messageId, parameters, wrapped);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/config/ConfigurationProvider.java b/id.server/src/at/gv/egovernment/moa/id/config/ConfigurationProvider.java
new file mode 100644
index 000000000..5d523ba62
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/config/ConfigurationProvider.java
@@ -0,0 +1,105 @@
+package at.gv.egovernment.moa.id.config;
+
+import java.math.BigInteger;
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.Map;
+
+import at.gv.egovernment.moa.id.data.IssuerAndSerial;
+
+/**
+ * Base class for <code>AuthConfigurationProvider</code> and <code>ProxyConfigurationProvider</code>,
+ * providing functions common to both of them.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ConfigurationProvider {
+
+ /**
+ * Constructor
+ */
+ public ConfigurationProvider() {
+ super();
+ }
+
+ /**
+ * The name of the system property which contains the file name of the
+ * configuration file.
+ */
+ public static final String CONFIG_PROPERTY_NAME =
+ "moa.id.configuration";
+
+ /**
+ * The name of the generic configuration property giving the certstore directory path.
+ */
+ public static final String DIRECTORY_CERTSTORE_PARAMETER_PROPERTY =
+ "DirectoryCertStoreParameters.RootDir";
+
+ /**
+ * A <code>Map</code> which contains generic configuration information. Maps a
+ * configuration name (a <code>String</code>) to a configuration value (also a
+ * <code>String</code>).
+ */
+ protected Map genericConfiguration;
+
+ /** The default chaining mode. */
+ protected String defaultChainingMode;
+
+ /**
+ * A <code>Map</code> which contains the <code>IssuerAndSerial</code> to
+ * chaining mode (a <code>String</code>) mapping.
+ */
+ protected Map chainingModes;
+
+ /**
+ * the URL for the trusted CA Certificates
+ */
+ protected String trustedCACertificates;
+
+ /**
+ * Returns the mapping of generic configuration properties.
+ *
+ * @return The mapping of generic configuration properties (a name to value
+ * mapping) from the configuration.
+ */
+ public Map getGenericConfiguration() {
+ return genericConfiguration;
+ }
+
+ /**
+ * Returns the value of a parameter from the generic configuration section.
+ *
+ * @return the parameter value; <code>null</code> if no such parameter
+ */
+ public String getGenericConfigurationParameter(String parameter) {
+ if (! genericConfiguration.containsKey(parameter))
+ return null;
+ return (String)genericConfiguration.get(parameter);
+ }
+
+ /**
+ * Return the chaining mode for a given trust anchor.
+ *
+ * @param trustAnchor The trust anchor for which the chaining mode should be
+ * returned.
+ * @return The chaining mode for the given trust anchor. If the trust anchor
+ * has not been configured separately, the system default will be returned.
+ */
+ public String getChainingMode(X509Certificate trustAnchor) {
+ Principal issuer = trustAnchor.getIssuerDN();
+ BigInteger serial = trustAnchor.getSerialNumber();
+ IssuerAndSerial issuerAndSerial = new IssuerAndSerial(issuer, serial);
+
+ String mode = (String) chainingModes.get(issuerAndSerial);
+ return mode != null ? mode : defaultChainingMode;
+ }
+
+ /**
+ * Returns the trustedCACertificates.
+ * @return String
+ */
+ public String getTrustedCACertificates() {
+ return trustedCACertificates;
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/config/ConnectionParameter.java b/id.server/src/at/gv/egovernment/moa/id/config/ConnectionParameter.java
new file mode 100644
index 000000000..30b09cfe0
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/config/ConnectionParameter.java
@@ -0,0 +1,106 @@
+package at.gv.egovernment.moa.id.config;
+
+/**
+ * This bean class is used to store data for various connectionParameter
+ * within the MOA-ID configuration
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class ConnectionParameter {
+
+ /**
+ * Server URL
+ */
+ private String url;
+ /**
+ * File URL for a directory containing PKCS#12 server SSL certificates.
+ * From these certificates, a X509 trust store will be assembled for use
+ * by a JSSE <code>TrustManager</code>.
+ * This field will only be used in case of an HTTPS URL.
+ */
+ private String acceptedServerCertificates;
+ /**
+ * File URL of a X509 key store containing the private key to be used
+ * for an HTTPS connection when the server requires client authentication.
+ * This field will only be used in case of an HTTPS URL.
+ */
+ private String clientKeyStore;
+ /**
+ * Password protecting the client key store.
+ */
+ private String clientKeyStorePassword;
+
+ /**
+ * Checks whether the URL scheme is <code>"https"</code>.
+ * @return true in case of an URL starting with <code>"https"</code>
+ */
+ public boolean isHTTPSURL() {
+ return getUrl().indexOf("https") == 0;
+ }
+
+ /**
+ * Returns the url.
+ * @return String
+ */
+ public String getUrl() {
+ return url;
+ }
+
+ /**
+ * Returns the acceptedServerCertificates.
+ * @return String
+ */
+ public String getAcceptedServerCertificates() {
+ return acceptedServerCertificates;
+ }
+
+ /**
+ * Sets the acceptedServerCertificates.
+ * @param acceptedServerCertificates The acceptedServerCertificates to set
+ */
+ public void setAcceptedServerCertificates(String acceptedServerCertificates) {
+ this.acceptedServerCertificates = acceptedServerCertificates;
+ }
+
+ /**
+ * Sets the url.
+ * @param url The url to set
+ */
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ /**
+ * Returns the clientKeyStore.
+ * @return String
+ */
+ public String getClientKeyStore() {
+ return clientKeyStore;
+ }
+
+ /**
+ * Returns the clientKeyStorePassword.
+ * @return String
+ */
+ public String getClientKeyStorePassword() {
+ return clientKeyStorePassword;
+ }
+
+ /**
+ * Sets the clientKeyStore.
+ * @param clientKeyStore The clientKeyStore to set
+ */
+ public void setClientKeyStore(String clientKeyStore) {
+ this.clientKeyStore = clientKeyStore;
+ }
+
+ /**
+ * Sets the clientKeyStorePassword.
+ * @param clientKeyStorePassword The clientKeyStorePassword to set
+ */
+ public void setClientKeyStorePassword(String clientKeyStorePassword) {
+ this.clientKeyStorePassword = clientKeyStorePassword;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java b/id.server/src/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java
new file mode 100644
index 000000000..e3c869d53
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java
@@ -0,0 +1,341 @@
+package at.gv.egovernment.moa.id.config.auth;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.config.ConfigurationBuilder;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConfigurationProvider;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.FileUtils;
+
+/**
+ * A class providing access to the Auth Part of the MOA-ID configuration data.
+ *
+ * <p>Configuration data is read from an XML file, whose location is given by
+ * the <code>moa.id.configuration</code> system property.</p>
+ * <p>This class implements the Singleton pattern. The <code>reload()</code>
+ * method can be used to update the configuration data. Therefore, it is not
+ * guaranteed that consecutive calls to <code>getInstance()</code> will return
+ * the same <code>AuthConfigurationProvider</code> all the time. During the
+ * processing of a web service request, the current
+ * <code>TransactionContext</code> should be used to obtain the
+ * <code>AuthConfigurationProvider</code> local to that request.</p>
+ *
+ * @author Patrick Peck
+ * @author Stefan Knirsch
+ *
+ * @version $Id$
+ */
+public class AuthConfigurationProvider extends ConfigurationProvider {
+
+ /** DEFAULT_ENCODING is "UTF-8" */
+ private static final String DEFAULT_ENCODING="UTF-8";
+ /**
+ * The name of the generic configuration property giving the authentication session time out.
+ */
+ public static final String AUTH_SESSION_TIMEOUT_PROPERTY =
+ "AuthenticationSession.TimeOut";
+ /**
+ * The name of the generic configuration property giving the authentication data time out.
+ */
+ public static final String AUTH_DATA_TIMEOUT_PROPERTY =
+ "AuthenticationData.TimeOut";
+
+ /**
+ * BKUSelectionType HTMLComplete, according to schema type <code>BKUSelectionType</code>
+ */
+ public static final String BKU_SELECTION_TYPE_HTMLCOMPLETE =
+ "HTMLComplete";
+
+ /**
+ * BKUSelectionType HTMLSelect, according to schema type <code>BKUSelectionType</code>
+ */
+ public static final String BKU_SELECTION_TYPE_HTMLSELECT =
+ "HTMLSelect";
+
+ /** Singleton instance. <code>null</code>, if none has been created. */
+ private static AuthConfigurationProvider instance;
+
+ //
+ // configuration data
+ //
+
+ /**
+ * configuration files containing transformations for rendering in the
+ * secure viewer of the security layer implementation;
+ * multiple files can be given for different mime types
+ */
+ private String[] transformsInfoFileNames;
+ /**
+ * transformations for rendering in the secure viewer of the security layer implementation,
+ * read from {@link transformsInfoFileNames};
+ * multiple transformation can be given for different mime types
+ */
+ private String[] transformsInfos;
+ /**
+ * parameters for connection to MOA SP component
+ */
+ private ConnectionParameter moaSpConnectionParameter;
+ /**
+ * trust profile ID to be used for verifying the identity link signature via MOA ID SP
+ */
+ private String moaSpIdentityLinkTrustProfileID;
+ /**
+ * trust profile ID to be used for verifying the AUTH block signature via MOA ID SP
+ */
+ private String moaSpAuthBlockTrustProfileID;
+ /**
+ * transformations to be used for verifying the AUTH block signature via MOA ID SP
+ */
+ private String[] moaSpAuthBlockVerifyTransformsInfoIDs;
+ /**
+ * X509 SubjectNames which will be trusted
+ */
+ private String[] identityLinkX509SubjectNames;
+
+ /**
+ * configuration parameters for online applications
+ */
+ private OAAuthParameter[] onlineApplicationAuthParameters;
+ /**
+ * the Selection Type of the bku Selection Element
+ */
+ private String bKUSelectionType;
+ /**
+ * is the bku Selection Element present?
+ */
+ private boolean bKUSelectable;
+ /**
+ * the bku Selection Connection Parameters
+ */
+ private ConnectionParameter bKUConnectionParameter;
+ /**
+ * Return the single instance of configuration data.
+ *
+ * @return AuthConfigurationProvider The current configuration data.
+ * @throws ConfigurationException
+ */
+ public static synchronized AuthConfigurationProvider getInstance()
+ throws ConfigurationException {
+
+ if (instance == null) {
+ reload();
+ }
+ return instance;
+ }
+
+ /**
+ * Reload the configuration data and set it if successful.
+ *
+ * @return AuthConfigurationProvider The loaded configuration data.
+ * @throws ConfigurationException Failure to load the configuration data.
+ */
+ public static synchronized AuthConfigurationProvider reload()
+ throws ConfigurationException {
+ String fileName = System.getProperty(ConfigurationProvider.CONFIG_PROPERTY_NAME);
+ if (fileName == null) {
+ throw new ConfigurationException("config.01", null);
+ }
+ Logger.info("Loading MOA-ID-AUTH configuration " + fileName);
+
+ instance = new AuthConfigurationProvider(fileName);
+ return instance;
+ }
+
+ /**
+ * Constructor for AuthConfigurationProvider.
+ * @param fileName
+ * @throws ConfigurationException
+ */
+ public AuthConfigurationProvider(String fileName)
+ throws ConfigurationException {
+
+ load(fileName);
+ }
+
+ /**
+ * Load the configuration data from XML file with the given name and build
+ * the internal data structures representing the MOA ID configuration.
+ *
+ * @param fileName The name of the XML file to load.
+ * @throws ConfigurationException The MOA configuration could not be
+ * read/built.
+ */
+ private void load(String fileName) throws ConfigurationException {
+ InputStream stream = null;
+ Element configElem;
+ ConfigurationBuilder builder;
+
+ try {
+ // load the main config file
+ stream = new BufferedInputStream(new FileInputStream(fileName));
+ configElem = DOMUtils.parseXmlValidating(stream);
+ } catch (Throwable t) {
+ throw new ConfigurationException("config.03", null, t);
+ }
+ finally {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+ try {
+ // build the internal datastructures
+ builder = new ConfigurationBuilder(configElem);
+ bKUConnectionParameter = builder.buildAuthBKUConnectionParameter();
+ bKUSelectable = (bKUConnectionParameter!=null);
+ bKUSelectionType = builder.buildAuthBKUSelectionType();
+ genericConfiguration = builder.buildGenericConfiguration();
+ transformsInfoFileNames = builder.buildTransformsInfoFileNames();
+ loadTransformsInfos();
+ moaSpConnectionParameter = builder.buildMoaSpConnectionParameter();
+ moaSpIdentityLinkTrustProfileID = builder.getMoaSpIdentityLinkTrustProfileID();
+ moaSpAuthBlockTrustProfileID = builder.getMoaSpAuthBlockTrustProfileID();
+ moaSpAuthBlockVerifyTransformsInfoIDs = builder.buildMoaSpAuthBlockVerifyTransformsInfoIDs();
+ onlineApplicationAuthParameters = builder.buildOnlineApplicationAuthParameters();
+ identityLinkX509SubjectNames = builder.getIdentityLink_X509SubjectNames();
+ defaultChainingMode = builder.getDefaultChainingMode();
+ chainingModes = builder.buildChainingModes();
+ trustedCACertificates = builder.getTrustedCACertificates(); }
+ catch (Throwable t) {
+ throw new ConfigurationException("config.02", null, t);
+ }
+ }
+
+ /**
+ * Loads the <code>transformsInfos</code> from files.
+ * @throws Exception on any exception thrown
+ */
+ private void loadTransformsInfos() throws Exception {
+ transformsInfos = new String[transformsInfoFileNames.length];
+ for (int i = 0; i < transformsInfoFileNames.length; i++) {
+ String fileURL = transformsInfoFileNames[i];
+ String transformsInfo = FileUtils.readURL(fileURL, DEFAULT_ENCODING);
+ transformsInfos[i] = transformsInfo;
+ }
+ }
+ /**
+ * Return a string array with all filenames leading
+ * to the Transforms Information for the Security Layer
+ * @return String[] of filenames to the Security Layer Transforms Information
+ */
+ public String[] getTransformsInfoFileNames() {
+ return transformsInfoFileNames;
+ }
+
+ /**
+ * Build an array of the OnlineApplication Parameters containing information
+ * about the authentication component
+ * @return An OAProxyParameter array containing beans
+ * with all relevant information for theauthentication component of the online
+ * application
+ */
+ public OAAuthParameter[] getOnlineApplicationParameters() {
+ return onlineApplicationAuthParameters;
+ }
+
+ /**
+ * Provides configuration information regarding the online application behind
+ * the given URL, relevant to the MOA-ID Auth component.
+ *
+ * @param oaURL URL requested for an online application
+ * @return an <code>OAAuthParameter</code>, or <code>null</code>
+ * if none is applicable
+ */
+ public OAAuthParameter getOnlineApplicationParameter(String oaURL) {
+ OAAuthParameter[] oaParams = getOnlineApplicationParameters();
+ for (int i = 0; i < oaParams.length; i++) {
+ OAAuthParameter oaParam = oaParams[i];
+ if (oaURL.indexOf(oaParam.getPublicURLPrefix()) == 0)
+ return oaParam;
+ }
+ return null;
+ }
+
+ /**
+ * Return a string with a url-reference to the VerifyAuthBlock trust
+ * profile id within the moa-sp part of the authentication component
+ *
+ * @return String with a url-reference to the VerifyAuthBlock trust profile ID
+ */
+ public String getMoaSpAuthBlockTrustProfileID() {
+ return moaSpAuthBlockTrustProfileID;
+ }
+
+ /**
+ * Return a string array with references to all verify transform info
+ * IDs within the moa-sp part of the authentication component
+ * @return A string array containing all urls to the
+ * verify transform info IDs
+ */
+ public String[] getMoaSpAuthBlockVerifyTransformsInfoIDs() {
+ return moaSpAuthBlockVerifyTransformsInfoIDs;
+ }
+
+ /**
+ * Return a ConnectionParameter bean containing all information
+ * of the authentication component moa-sp element
+ * @return ConnectionParameter of the authentication component moa-sp element
+ */
+ public ConnectionParameter getMoaSpConnectionParameter() {
+ return moaSpConnectionParameter;
+ }
+
+ /**
+ * Return a string with a url-reference to the VerifyIdentityLink trust
+ * profile id within the moa-sp part of the authentication component
+ * @return String with a url-reference to the VerifyIdentityLink trust profile ID
+ */
+ public String getMoaSpIdentityLinkTrustProfileID() {
+ return moaSpIdentityLinkTrustProfileID;
+ }
+ /**
+ * Returns the transformsInfos.
+ * @return String[]
+ */
+ public String[] getTransformsInfos() {
+ return transformsInfos;
+ }
+
+ /**
+ * Returns the identityLinkX509SubjectNames.
+ * @return String[]
+ */
+ public String[] getIdentityLinkX509SubjectNames() {
+ return identityLinkX509SubjectNames;
+ }
+
+ /**
+ * Returns the bKUConnectionParameter.
+ * @return ConnectionParameter
+ */
+ public ConnectionParameter getBKUConnectionParameter() {
+ return bKUConnectionParameter;
+ }
+
+ /**
+ * Returns the bKUSelectable.
+ * @return boolean
+ */
+ public boolean isBKUSelectable() {
+ return bKUSelectable;
+ }
+
+ /**
+ * Returns the bKUSelectionType.
+ * @return String
+ */
+ public String getBKUSelectionType() {
+ return bKUSelectionType;
+ }
+
+} \ No newline at end of file
diff --git a/id.server/src/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java b/id.server/src/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java
new file mode 100644
index 000000000..9ee1ec606
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java
@@ -0,0 +1,93 @@
+package at.gv.egovernment.moa.id.config.auth;
+
+/**
+ * Configuration parameters belonging to an online application,
+ * to use with the MOA ID Auth component.
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class OAAuthParameter {
+
+ /**
+ * public URL prefix of the online application
+ */
+ private String publicURLPrefix;
+ /**
+ * determines whether "ZMR-Zahl" is to be included in the authentication data
+ */
+ private boolean provideZMRZahl;
+ /**
+ * determines whether AUTH block is to be included in the authentication data
+ */
+ private boolean provideAuthBlock;
+ /**
+ * determines whether identity link is to be included in the authentication data
+ */
+ private boolean provideIdentityLink;
+
+ /**
+ * Returns the provideAuthBlock.
+ * @return String
+ */
+ public boolean getProvideAuthBlock() {
+ return provideAuthBlock;
+ }
+
+ /**
+ * Returns the provideIdentityLink.
+ * @return String
+ */
+ public boolean getProvideIdentityLink() {
+ return provideIdentityLink;
+ }
+
+ /**
+ * Returns the provideZMRZahl.
+ * @return String
+ */
+ public boolean getProvideZMRZahl() {
+ return provideZMRZahl;
+ }
+
+ /**
+ * Returns the publicURLPrefix.
+ * @return String
+ */
+ public String getPublicURLPrefix() {
+ return publicURLPrefix;
+ }
+
+ /**
+ * Sets the provideAuthBlock.
+ * @param provideAuthBlock The provideAuthBlock to set
+ */
+ public void setProvideAuthBlock(boolean provideAuthBlock) {
+ this.provideAuthBlock = provideAuthBlock;
+ }
+
+ /**
+ * Sets the provideIdentityLink.
+ * @param provideIdentityLink The provideIdentityLink to set
+ */
+ public void setProvideIdentityLink(boolean provideIdentityLink) {
+ this.provideIdentityLink = provideIdentityLink;
+ }
+
+ /**
+ * Sets the provideZMRZahl.
+ * @param provideZMRZahl The provideZMRZahl to set
+ */
+ public void setProvideZMRZahl(boolean provideZMRZahl) {
+ this.provideZMRZahl = provideZMRZahl;
+ }
+
+ /**
+ * Sets the publicURLPrefix.
+ * @param publicURLPrefix The publicURLPrefix to set
+ */
+ public void setPublicURLPrefix(String publicURLPrefix) {
+ this.publicURLPrefix = publicURLPrefix;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/config/proxy/OAConfiguration.java b/id.server/src/at/gv/egovernment/moa/id/config/proxy/OAConfiguration.java
new file mode 100644
index 000000000..c9a13fee5
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/config/proxy/OAConfiguration.java
@@ -0,0 +1,145 @@
+package at.gv.egovernment.moa.id.config.proxy;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Holds configuration data concerning an online application for use by the MOA-ID Proxy component.
+ * These include the login type (stateful or stateless), the HTTP authentication type,
+ * and information needed to add authentication parameters or headers for a URL connection
+ * to the remote online application.
+ * @see <code>MOAIDConfiguration-1.1.xsd</code>, element <code>Configuration</code>
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class OAConfiguration {
+
+ /** Constant for an login method */
+ public static final String LOGINTYPE_STATEFUL = "stateful";
+ /** Constant for an login method */
+ public static final String LOGINTYPE_STATELESS = "stateless";
+
+ /** Constant for an auth method */
+ public static final String BASIC_AUTH = "basic";
+ /** Constant for an auth method */
+ public static final String HEADER_AUTH = "header";
+ /** Constant for an auth method */
+ public static final String PARAM_AUTH = "param";
+
+ /** login type: stateful or stateless */
+ String loginType;
+ /** authentication type: basic, header, or param */
+ String authType;
+ /**
+ * mapping of parameter names to AuthenticationData field names
+ * in case of authentication type <code>"header-auth"</code>
+ */
+ Map paramAuthMapping;
+ /**
+ * mapping of parameter names to AuthenticationData field names
+ * in case of authentication type <code>"param-auth"</code>
+ */
+ Map headerAuthMapping;
+ /** mapping for user ID to be used in case of authentication type <code>"basic-auth"</code> */
+ String basicAuthUserIDMapping;
+ /** mapping for password to be used in case of authentication type <code>"basic-auth"</code> */
+ String basicAuthPasswordMapping;
+
+ /**
+ * Returns the basicAuthPasswordMapping.
+ * @return String
+ */
+ public String getBasicAuthPasswordMapping() {
+ return basicAuthPasswordMapping;
+ }
+
+ /**
+ * Returns the basicAuthUserIDMapping.
+ * @return String
+ */
+ public String getBasicAuthUserIDMapping() {
+ return basicAuthUserIDMapping;
+ }
+
+ /**
+ * Returns the headerAuthMapping.
+ * @return HashMap
+ */
+ public Map getHeaderAuthMapping() {
+ return headerAuthMapping;
+ }
+
+ /**
+ * Returns the loginType.
+ * @return String
+ */
+ public String getLoginType() {
+ return loginType;
+ }
+
+ /**
+ * Returns the paramAuthMapping.
+ * @return HashMap
+ */
+ public Map getParamAuthMapping() {
+ return paramAuthMapping;
+ }
+
+ /**
+ * Sets the basicAuthPasswordMapping.
+ * @param basicAuthPasswordMapping The basicAuthPasswordMapping to set
+ */
+ public void setBasicAuthPasswordMapping(String basicAuthPassword) {
+ this.basicAuthPasswordMapping = basicAuthPassword;
+ }
+
+ /**
+ * Sets the basicAuthUserIDMapping.
+ * @param basicAuthUserIDMapping The basicAuthUserIDMapping to set
+ */
+ public void setBasicAuthUserIDMapping(String basicAuthUserID) {
+ this.basicAuthUserIDMapping = basicAuthUserID;
+ }
+
+ /**
+ * Sets the headerAuthMapping.
+ * @param headerAuthMapping The headerAuthMapping to set
+ */
+ public void setHeaderAuthMapping(HashMap headerAuth) {
+ this.headerAuthMapping = headerAuth;
+ }
+
+ /**
+ * Sets the loginType.
+ * @param loginType The loginType to set
+ */
+ public void setLoginType(String loginType) {
+ this.loginType = loginType;
+ }
+
+ /**
+ * Sets the paramAuthMapping.
+ * @param paramAuthMapping The paramAuthMapping to set
+ */
+ public void setParamAuthMapping(HashMap paramAuth) {
+ this.paramAuthMapping = paramAuth;
+ }
+
+ /**
+ * Returns the authType.
+ * @return String
+ */
+ public String getAuthType() {
+ return authType;
+ }
+
+ /**
+ * Sets the authType.
+ * @param authType The authType to set
+ */
+ public void setAuthType(String authLoginType) {
+ this.authType = authLoginType;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/config/proxy/OAProxyParameter.java b/id.server/src/at/gv/egovernment/moa/id/config/proxy/OAProxyParameter.java
new file mode 100644
index 000000000..f08c60736
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/config/proxy/OAProxyParameter.java
@@ -0,0 +1,160 @@
+package at.gv.egovernment.moa.id.config.proxy;
+
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+
+/**
+ * Configuration parameters belonging to an online application,
+ * to use with the MOA ID Proxy component.
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ */
+public class OAProxyParameter {
+
+ /**
+ * public URL prefix of the online application
+ */
+ private String publicURLPrefix;
+ /**
+ * URL of online application configuration file;
+ * defaults to relative URL <code>/moaconfig.xml</code>
+ */
+ private String configFileURL;
+ /**
+ * implementation of {@link at.gv.egovernment.moa.id.proxy.LoginParameterResolver} interface
+ * to be used for authenticating the online application;
+ * defaults to {@link at.gv.egovernment.moa.id.proxy.DefaultLoginParameterResolver}
+ */
+ private String loginParameterResolverImpl;
+ /**
+ * implementation of {@link at.gv.egovernment.moa.id.proxy.ConnectionBuilder} interface
+ * to be used for connecting to the online application;
+ * defaults to {@link at.gv.egovernment.moa.id.proxy.DefaultConnectionBuilder}
+ */
+ private String connectionBuilderImpl;
+ /**
+ * session time out to be used in case of a stateless online application
+ */
+ private int sessionTimeOut;
+ /**
+ * parameters regarding the connection from the proxy to the online application
+ */
+ private ConnectionParameter connectionParameter;
+ /**
+ * parameters for logging into the online application
+ */
+ private OAConfiguration oaConfiguration;
+
+ /**
+ * Returns the configFileURL.
+ * @return String
+ */
+ public String getConfigFileURL() {
+ return configFileURL;
+ }
+
+ /**
+ * Returns the sessionTimeOut.
+ * @return int
+ */
+ public int getSessionTimeOut() {
+ return sessionTimeOut;
+ }
+
+ /**
+ * Returns the connectionParameter.
+ * @return ConnectionParameter
+ */
+ public ConnectionParameter getConnectionParameter() {
+ return connectionParameter;
+ }
+
+ /**
+ * Sets the configFileURL.
+ * @param configFileURL The configFileURL to set
+ */
+ public void setConfigFileURL(String oaProxyConfigFileURL) {
+ this.configFileURL = oaProxyConfigFileURL;
+ }
+
+ /**
+ * Sets the sessionTimeOut.
+ * @param sessionTimeOut The sessionTimeOut to set
+ */
+ public void setSessionTimeOut(int oaProxySessionTimeOut) {
+ this.sessionTimeOut = oaProxySessionTimeOut;
+ }
+
+ /**
+ * Sets the connectionParameter.
+ * @param connectionParameter The connectionParameter to set
+ */
+ public void setConnectionParameter(ConnectionParameter proxyConnectionParameter) {
+ this.connectionParameter = proxyConnectionParameter;
+ }
+
+ /**
+ * Returns the publicURLPrefix.
+ * @return String
+ */
+ public String getPublicURLPrefix() {
+ return publicURLPrefix;
+ }
+
+ /**
+ * Sets the publicURLPrefix.
+ * @param publicURLPrefix The publicURLPrefix to set
+ */
+ public void setPublicURLPrefix(String url) {
+ this.publicURLPrefix = url;
+ }
+
+ /**
+ * Returns the connectionBuilderImpl.
+ * @return String
+ */
+ public String getConnectionBuilderImpl() {
+ return connectionBuilderImpl;
+ }
+
+ /**
+ * Returns the loginParameterResolverImpl.
+ * @return String
+ */
+ public String getLoginParameterResolverImpl() {
+ return loginParameterResolverImpl;
+ }
+
+ /**
+ * Sets the connectionBuilderImpl.
+ * @param connectionBuilderImpl The connectionBuilderImpl to set
+ */
+ public void setConnectionBuilderImpl(String connectionBuilderImp) {
+ this.connectionBuilderImpl = connectionBuilderImp;
+ }
+
+ /**
+ * Sets the loginParameterResolverImpl.
+ * @param loginParameterResolverImpl The loginParameterResolverImpl to set
+ */
+ public void setLoginParameterResolverImpl(String loginParameterResolverImpl) {
+ this.loginParameterResolverImpl = loginParameterResolverImpl;
+ }
+
+ /**
+ * Returns the oaConfiguration.
+ * @return OAConfiguration
+ */
+ public OAConfiguration getOaConfiguration() {
+ return oaConfiguration;
+ }
+
+ /**
+ * Sets the oaConfiguration.
+ * @param oaConfiguration The oaConfiguration to set
+ */
+ public void setOaConfiguration(OAConfiguration oaConfiguration) {
+ this.oaConfiguration = oaConfiguration;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/config/proxy/ProxyConfigurationProvider.java b/id.server/src/at/gv/egovernment/moa/id/config/proxy/ProxyConfigurationProvider.java
new file mode 100644
index 000000000..897d14da9
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/config/proxy/ProxyConfigurationProvider.java
@@ -0,0 +1,170 @@
+package at.gv.egovernment.moa.id.config.proxy;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.config.ConfigurationBuilder;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConfigurationProvider;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+
+/**
+ * A class providing access to the Proxy Part of the MOA-ID configuration data.
+ *
+ * <p>Configuration data is read from an XML file, whose location is given by
+ * the <code>moa.id.configuration</code> system property.</p>
+ * <p>This class implements the Singleton pattern. The <code>reload()</code>
+ * method can be used to update the configuration data. Therefore, it is not
+ * guaranteed that consecutive calls to <code>getInstance()</code> will return
+ * the same <code>ProxyConfigurationProvider</code> all the time. During the
+ * processing of a web service request, the current
+ * <code>TransactionContext</code> should be used to obtain the
+ * <code>ProxyConfigurationProvider</code> local to that request.</p>
+ *
+ * @author Stefan Knirsch
+ */
+public class ProxyConfigurationProvider extends ConfigurationProvider {
+
+ /** Singleton instance. <code>null</code>, if none has been created. */
+ private static ProxyConfigurationProvider instance;
+
+ //
+ // configuration data
+ //
+ /**
+ * connection parameters for connection to MOA ID Auth component
+ */
+ private ConnectionParameter authComponentConnectionParameter;
+ /**
+ * configuration parameters for online applications
+ */
+ private OAProxyParameter[] onlineApplicationProxyParameter;
+
+ /**
+ * Return the single instance of configuration data.
+ *
+ * @return ProxyConfigurationProvider The current configuration data.
+ * @throws ConfigurationException
+ */
+ public static synchronized ProxyConfigurationProvider getInstance()
+ throws ConfigurationException {
+
+ if (instance == null) {
+ reload();
+ }
+ return instance;
+ }
+
+ /**
+ * Reload the configuration data and set it if successful.
+ *
+ * @return ProxyConfigurationProvider The loaded configuration data.
+ * @throws ConfigurationException Failure to load the configuration data.
+ */
+ public static synchronized ProxyConfigurationProvider reload()
+ throws ConfigurationException {
+ String fileName = System.getProperty(CONFIG_PROPERTY_NAME);
+ if (fileName == null) {
+ throw new ConfigurationException("config.01", null);
+ }
+ Logger.info("Loading MOA-ID-PROXY configuration " + fileName);
+
+ instance = new ProxyConfigurationProvider(fileName);
+ return instance;
+ }
+
+ /**
+ * Constructor for ProxyConfigurationProvider.
+ */
+ public ProxyConfigurationProvider(String fileName)
+ throws ConfigurationException {
+
+ load(fileName);
+ }
+
+ /**
+ * Load the configuration data from XML file with the given name and build
+ * the internal data structures representing the MOA configuration.
+ *
+ * @param fileName The name of the XML file to load.
+ * @throws ConfigurationException The MOA configuration could not be
+ * read/built.
+ */
+ private void load(String fileName) throws ConfigurationException {
+ FileInputStream stream = null;
+ Element configElem;
+ ConfigurationBuilder builder;
+
+ try {
+ // load the main config file
+ stream = new FileInputStream(fileName);
+ configElem = DOMUtils.parseXmlValidating(stream);
+ }
+ catch (Throwable t) {
+ throw new ConfigurationException("config.03", null, t);
+ }
+ finally {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ catch (IOException e) {
+ }
+ }
+ try {
+ // build the internal datastructures
+ builder = new ConfigurationBuilder(configElem);
+ authComponentConnectionParameter = builder.buildAuthComponentConnectionParameter();
+ onlineApplicationProxyParameter = builder.buildOnlineApplicationProxyParameters();
+ genericConfiguration = builder.buildGenericConfiguration();
+ defaultChainingMode = builder.getDefaultChainingMode();
+ chainingModes = builder.buildChainingModes();
+ trustedCACertificates = builder.getTrustedCACertificates();
+ }
+ catch (Throwable t) {
+ throw new ConfigurationException("config.02", null, t);
+ }
+ }
+
+ /**
+ * Return a bean containing all information about the ProxyComponent
+ * @return The ConnectionParameter for the Proxy Component
+ */
+ public ConnectionParameter getAuthComponentConnectionParameter() {
+ return authComponentConnectionParameter;
+ }
+
+ /**
+ * Build an array of OnlineApplication Parameter Beans containing all
+ * information about the proxy component of the online application
+ * @return An OAProxyParameter array containing beans
+ * with all relevant information for the proxy component of the online
+ * application
+ */
+ public OAProxyParameter[] getOnlineApplicationParameters() {
+ return onlineApplicationProxyParameter;
+ }
+ /**
+ * Provides configuration information regarding the online application behind
+ * the given URL, relevant to the MOA-ID Proxy component.
+ *
+ * @param oaURL URL requested for an online application
+ * @return an <code>OAProxyParameter</code>, or <code>null</code>
+ * if none is applicable
+ */
+ public OAProxyParameter getOnlineApplicationParameter(String oaURL) {
+ OAProxyParameter[] oaParams = getOnlineApplicationParameters();
+ for (int i = 0; i < oaParams.length; i++) {
+ OAProxyParameter oaParam = oaParams[i];
+ if (oaURL.startsWith(oaParam.getPublicURLPrefix()))
+ return oaParam;
+ }
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/id.server/src/at/gv/egovernment/moa/id/data/AuthenticationData.java b/id.server/src/at/gv/egovernment/moa/id/data/AuthenticationData.java
new file mode 100644
index 000000000..aac1dc422
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/data/AuthenticationData.java
@@ -0,0 +1,314 @@
+package at.gv.egovernment.moa.id.data;
+
+import java.util.Date;
+
+/**
+ * Encapsulates authentication data contained in a <code>&lt;saml:Assertion&gt;</code>.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+
+public class AuthenticationData {
+ /**
+ * major version number of the SAML assertion
+ */
+ private int majorVersion;
+ /**
+ * minor version number of the SAML assertion
+ */
+ private int minorVersion;
+ /**
+ * identifier for this assertion
+ */
+ private String assertionID;
+ /**
+ * URL of the MOA-ID Auth component issueing this assertion
+ */
+ private String issuer;
+ /**
+ * time instant of issue of this assertion
+ */
+ private String issueInstant;
+ /**
+ * user identification (ZMR-Zahl); <code>null</code>,
+ * if the authentication module is configured not to return this data
+ */
+ private String identificationValue;
+ /**
+ * application specific user identifier (VPK)
+ */
+ private String vpk;
+ /**
+ * given name of the user
+ */
+ private String givenName;
+ /**
+ * family name of the user
+ */
+ private String familyName;
+ /**
+ * date of birth of the user
+ */
+ private String dateOfBirth;
+ /**
+ * says whether the certificate is a qualified certificate or not
+ */
+ private boolean qualifiedCertificate;
+ /**
+ * says whether the certificate is a public authority or not
+ */
+ private boolean publicAuthority;
+ /**
+ * public authority code (Beh&ouml;rdenkennzeichen - BKZ)
+ */
+ private String publicAuthorityCode;
+ /**
+ * the corresponding <code>lt;saml:Assertion&gt;</code>
+ */
+ private String samlAssertion;
+ /**
+ * creation timestamp
+ */
+ Date timestamp;
+
+ /**
+ * Constructor for AuthenticationData.
+ */
+ public AuthenticationData() {
+ timestamp = new Date();
+ }
+
+ /**
+ * Returns the minorVersion.
+ * @return int
+ */
+ public int getMinorVersion() {
+ return minorVersion;
+ }
+
+ /**
+ * Returns the publicAuthority.
+ * @return boolean
+ */
+ public boolean isPublicAuthority() {
+ return publicAuthority;
+ }
+
+ /**
+ * Returns the publicAuthorityCode.
+ * @return String
+ */
+ public String getPublicAuthorityCode() {
+ return publicAuthorityCode;
+ }
+
+ /**
+ * Returns the qualifiedCertificate.
+ * @return boolean
+ */
+ public boolean isQualifiedCertificate() {
+ return qualifiedCertificate;
+ }
+
+ /**
+ * Returns the vpk.
+ * @return String
+ */
+ public String getVPK() {
+ return vpk;
+ }
+
+ /**
+ * Sets the minorVersion.
+ * @param minorVersion The minorVersion to set
+ */
+ public void setMinorVersion(int minorVersion) {
+ this.minorVersion = minorVersion;
+ }
+
+ /**
+ * Sets the publicAuthority.
+ * @param publicAuthority The publicAuthority to set
+ */
+ public void setPublicAuthority(boolean publicAuthority) {
+ this.publicAuthority = publicAuthority;
+ }
+
+ /**
+ * Sets the publicAuthorityCode.
+ * @param publicAuthorityCode The publicAuthorityCode to set
+ */
+ public void setPublicAuthorityCode(String publicAuthorityIdentification) {
+ this.publicAuthorityCode = publicAuthorityIdentification;
+ }
+
+ /**
+ * Sets the qualifiedCertificate.
+ * @param qualifiedCertificate The qualifiedCertificate to set
+ */
+ public void setQualifiedCertificate(boolean qualifiedCertificate) {
+ this.qualifiedCertificate = qualifiedCertificate;
+ }
+
+ /**
+ * Sets the vpk.
+ * @param vpk The vpk to set
+ */
+ public void setVPK(String vpk) {
+ this.vpk = vpk;
+ }
+
+ /**
+ * Returns the assertionID.
+ * @return String
+ */
+ public String getAssertionID() {
+ return assertionID;
+ }
+
+ /**
+ * Returns the dateOfBirth.
+ * @return String
+ */
+ public String getDateOfBirth() {
+ return dateOfBirth;
+ }
+
+ /**
+ * Returns the familyName.
+ * @return String
+ */
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ /**
+ * Returns the givenName.
+ * @return String
+ */
+ public String getGivenName() {
+ return givenName;
+ }
+
+ /**
+ * Returns the identificationValue.
+ * @return String
+ */
+ public String getIdentificationValue() {
+ return identificationValue;
+ }
+
+ /**
+ * Returns the issueInstant.
+ * @return String
+ */
+ public String getIssueInstant() {
+ return issueInstant;
+ }
+
+ /**
+ * Returns the issuer.
+ * @return String
+ */
+ public String getIssuer() {
+ return issuer;
+ }
+
+ /**
+ * Returns the majorVersion.
+ * @return int
+ */
+ public int getMajorVersion() {
+ return majorVersion;
+ }
+
+ /**
+ * Sets the assertionID.
+ * @param assertionID The assertionID to set
+ */
+ public void setAssertionID(String assertionID) {
+ this.assertionID = assertionID;
+ }
+
+ /**
+ * Sets the dateOfBirth.
+ * @param dateOfBirth The dateOfBirth to set
+ */
+ public void setDateOfBirth(String dateOfBirth) {
+ this.dateOfBirth = dateOfBirth;
+ }
+
+ /**
+ * Sets the familyName.
+ * @param familyName The familyName to set
+ */
+ public void setFamilyName(String gamilyName) {
+ this.familyName = gamilyName;
+ }
+
+ /**
+ * Sets the givenName.
+ * @param givenName The givenName to set
+ */
+ public void setGivenName(String givenName) {
+ this.givenName = givenName;
+ }
+
+ /**
+ * Sets the identificationValue.
+ * @param identificationValue The identificationValue to set
+ */
+ public void setIdentificationValue(String identificationValue) {
+ this.identificationValue = identificationValue;
+ }
+
+ /**
+ * Sets the issueInstant.
+ * @param issueInstant The issueInstant to set
+ */
+ public void setIssueInstant(String issueInstant) {
+ this.issueInstant = issueInstant;
+ }
+
+ /**
+ * Sets the issuer.
+ * @param issuer The issuer to set
+ */
+ public void setIssuer(String issuer) {
+ this.issuer = issuer;
+ }
+
+ /**
+ * Sets the majorVersion.
+ * @param majorVersion The majorVersion to set
+ */
+ public void setMajorVersion(int majorVersion) {
+ this.majorVersion = majorVersion;
+ }
+
+ /**
+ * Returns the samlAssertion.
+ * @return String
+ */
+ public String getSamlAssertion() {
+ return samlAssertion;
+ }
+
+ /**
+ * Sets the samlAssertion.
+ * @param samlAssertion The samlAssertion to set
+ */
+ public void setSamlAssertion(String samlAssertion) {
+ this.samlAssertion = samlAssertion;
+ }
+
+ /**
+ * Returns the timestamp.
+ * @return Date
+ */
+ public Date getTimestamp() {
+ return timestamp;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/data/Cookie.java b/id.server/src/at/gv/egovernment/moa/id/data/Cookie.java
new file mode 100644
index 000000000..5729e54c3
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/data/Cookie.java
@@ -0,0 +1,119 @@
+package at.gv.egovernment.moa.id.data;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * The Cookie-class provides methods to save and return cookies for
+ * each single session
+ *
+ * @author Stefan Knirsch
+ * @version $Id$
+ *
+ */
+public class Cookie {
+ /** A HahsMap containing all our cookies */
+ HashMap cookies = new HashMap();
+ /** A HashMap to temporarely store 'Set-Cookie' values from the OnlineApplication
+ * to send them back to the client/browser as soon as possible */
+ HashMap cookies401 = new HashMap();
+
+ /**
+ * Adds a Cookie from a response with response-code 401 to the cookie-pool
+ * for sending it back to the browser / client
+ * @param String: the complete 'Set-Cookie' - String
+ */
+ public void add401(String cookieString)
+ {
+ cookies401.put(getKey(cookieString),cookieString);
+ }
+
+ /**
+ * Get the HashMap containing all cookies to be sent to the browser / client
+ * @return HashMap with all cookies
+ */
+ public HashMap get401()
+ {
+ return cookies401;
+ }
+
+ /**
+ * Clear the 401 cookie-pool
+ */
+ public void clear401()
+ {
+ cookies401.clear();
+ }
+
+ /**
+ * Set a cookie that comes from the Online-Application
+ * and save it in our "normal" cookie-pool
+ * @param String the complete "Set-Cookie" - String from the Online-Application
+ */
+ public void setCookie(String value) {
+ cookies.put(getKey(value), getValue(value));
+ }
+
+ /**
+ * Method saveOldCookies.
+ * @param String the complete "Set-Cookie" - String from the Online-Application
+ */
+ public void saveOldCookies(String value) {
+ StringTokenizer st = new StringTokenizer(value,";");
+ while (st.hasMoreTokens())
+ {
+ // We have to trim because the Tokenizer returns cookies including spaces at the beginning
+ StringTokenizer st2 = new StringTokenizer(st.nextToken().trim(),"=");
+ String cookieKey = st2.nextToken().trim();
+ if (st2.hasMoreTokens())
+ {
+ String cookieValue = st2.nextToken().trim();
+ if (!cookies.containsKey(cookieKey))
+ cookies.put(cookieKey , cookieValue);
+ }
+ }
+ Logger.debug("Found these cookies: " + getCookies());
+ }
+
+ /**
+ * Get a String containing all cookies saved in that session seperated by '; '
+ * to be sent back to the Online-Application
+ * @return String containing all cookies saved in that session seperated by '; '
+ */
+ public String getCookies() {
+ String result = "";
+ if (cookies.size()==0)
+ return null;
+ Iterator i = cookies.keySet().iterator();
+ while (i.hasNext()) {
+ String key = (String) i.next();
+ result += key + "=" + (String)cookies.get(key) + "; ";
+ }
+ return result.substring(0, result.length() - 2);
+ }
+
+ /**
+ * Returns the key of a key-value-pair of a cookie
+ * getKey("CookieA=1234") returns CookieA
+ * @param String the complete "Set-cookie" String containing a key-value-pair of a cookie
+ * @return String the key of a key-value-pair of a cookie
+ */
+ private String getKey(String input) {
+ return input.substring(0, input.indexOf("="));
+ }
+
+ /**
+ * Returns the value of a key-value-pair of a cookie
+ * getKey("CookieA=1234") returns 1234
+ * @param String the complete "Set-cookie" String containing a key-value-pair of a cookie
+ * @return String the value of a key-value-pair of a cookie
+ */
+ private String getValue(String input) {
+ if (input.indexOf(";") == -1)
+ return input.substring(input.indexOf("=") + 1, input.getBytes().length);
+ return input.substring(input.indexOf("=") + 1, input.indexOf(";"));
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/data/CookieManager.java b/id.server/src/at/gv/egovernment/moa/id/data/CookieManager.java
new file mode 100644
index 000000000..98f84c429
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/data/CookieManager.java
@@ -0,0 +1,114 @@
+package at.gv.egovernment.moa.id.data;
+
+import java.util.HashMap;
+
+/**
+ * The CookieManager is a singleton to manage a Cookie-Object for
+ * each session
+ * @author Stefan Knirsch
+ * @version $Id$
+ *
+ */
+public class CookieManager {
+ /** the singleton instance of the CookieManager */
+ private static CookieManager instance;
+ /** a HashMap to bind a Cookie-object to every single session*/
+ private static HashMap cookies = new HashMap();
+
+ /**
+ * Create a singleton of the CookieManager
+ * @return CookieManager
+ */
+ public static CookieManager getInstance()
+ {
+ if(instance==null) instance=new CookieManager();
+ return instance;
+ }
+
+ /**
+ * Save a cookie to a specified session-id
+ * @param String id the session id
+ * @param String cookie_string - the complete 'Set-Cookie' String from the OnlineApplication
+ */
+ public void saveCookie(String id,String cookie_string)
+ {
+ getCookieWithID(id).setCookie(cookie_string);
+ }
+
+ /**
+ * Method saveOldCookies.
+ * @param id
+ * @param cookie_string
+ */
+ public void saveOldCookies(String id,String cookie_string)
+ {
+ getCookieWithID(id).saveOldCookies(cookie_string);
+ }
+
+ /**
+ * Get a Cookie-Object for a specified session-id
+ * @param String id the session id
+ * @return Cookie object containing all saved cookies for this session
+ */
+ public Cookie getCookieWithID(String id)
+ {
+ Cookie c = null;
+ if(cookies.containsKey(id))
+ c = (Cookie)cookies.get(id);
+ else
+ {
+ c = new Cookie();
+ cookies.put(id,c);
+ }
+ return c;
+ }
+
+
+ /**
+ * Get a String containing all cookies of a specified session-id
+ * saved in that session seperated by '; ' to be sent back to
+ * the Online-Application
+ * @param id the session-id
+ * @return String containing all cookies saved in that session seperated by '; '
+ */
+ public String getCookie(String id)
+ {
+ Cookie result = (Cookie)cookies.get((String)id);
+ if (result==null)
+ return null;
+ return result.getCookies();
+
+ }
+
+ /**
+ * Adds a Cookie for a special session from a response with
+ * response-code 401 to the cookie-pool for sending it back
+ * to the browser / client
+ * @param id the session-id
+ * @param String: the complete 'Set-Cookie' - String
+ */
+ public void add401(String id,String value)
+ {
+ getCookieWithID(id).add401(value);
+ }
+
+ /**
+ * Clear the 401 cookie-pool of a session
+ * @param id the session-id
+ */
+ public void clear401(String id)
+ {
+ getCookieWithID(id).clear401();
+ }
+
+ /**
+ * Get the HashMap containing all cookies of a session to be sent to the browser / client
+ * @param id the session-id
+ * @return HashMap with all cookies
+ */
+ public HashMap get401(String id)
+ {
+ return getCookieWithID(id).get401();
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/data/IssuerAndSerial.java b/id.server/src/at/gv/egovernment/moa/id/data/IssuerAndSerial.java
new file mode 100644
index 000000000..a47dd8b29
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/data/IssuerAndSerial.java
@@ -0,0 +1,111 @@
+package at.gv.egovernment.moa.id.data;
+
+import java.math.BigInteger;
+import java.security.Principal;
+
+import iaik.asn1.structures.Name;
+import iaik.utils.RFC2253NameParser;
+import iaik.utils.RFC2253NameParserException;
+
+/**
+ * A class containing the issuer and serial number of a certificate, which can
+ * be used to uniquely identify the certificate.
+ *
+ * @author Patrick Peck
+ * @version $Id$
+ */
+public class IssuerAndSerial {
+ /** store the issuer as String*/
+ private String issuerDN;
+ /** store the serial as BigInteger*/
+ private BigInteger serial;
+
+ /**
+ * Create an <code>IssuerAndSerial</code> object.
+ *
+ * The name of the issuer is converted to RFC2253. If it cannot be parsed, the
+ * DN contained in the <code>issuer</code> is set.
+ *
+ * @param issuer The isser of a certificate.
+ * @param serial The serial number of the certificate.
+ */
+ public IssuerAndSerial(Principal issuer, BigInteger serial) {
+ RFC2253NameParser parser = new RFC2253NameParser(issuer.getName());
+
+ try {
+ this.issuerDN = ((Name) parser.parse()).getRFC2253String();
+ } catch (RFC2253NameParserException e) {
+ this.issuerDN = issuer.getName();
+ }
+ this.serial = serial;
+ }
+
+ /**
+ * Create an <code>IssuerAndSerial</code> object.
+ *
+ * @param issuerDN The issuer distinguished name. Should be an RFC2253 name.
+ * @param serial The serial number of the certificate.
+ */
+ public IssuerAndSerial(String issuerDN, BigInteger serial) {
+ this.issuerDN = issuerDN;
+ this.serial = serial;
+ }
+
+ /**
+ * Return the issuer DN in RFC2253 format.
+ *
+ * @return The issuer part of this object.
+ */
+ public String getIssuerDN() {
+ return issuerDN;
+ }
+
+ /**
+ * Return the serial number.
+ *
+ * @return The serial number of this object.
+ */
+ public BigInteger getSerial() {
+ return serial;
+ }
+
+ /**
+ * Compare this <code>IssuerAndSerial</code> to another object.
+ *
+ * @return <code>true</code>, if <code>other</code> is an
+ * <code>IssuerAndSerial</code> object and the <code>issuer</code> and
+ * <code>serial</code> fields are both equal. <code>false</code> otherwise.
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object other) {
+ if (other instanceof IssuerAndSerial) {
+ IssuerAndSerial ias = (IssuerAndSerial) other;
+ return getIssuerDN().equals(ias.getIssuerDN())
+ && getSerial().equals(ias.getSerial());
+ }
+ return false;
+ }
+
+ /**
+ * Return the hash code of this <code>IssuerAndSerial</code>.
+ *
+ * @return The hash code of this <code>IssuerAndSerial</code>.
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return issuerDN.hashCode() ^ serial.hashCode();
+ }
+
+ /**
+ * Return a <code>String</code> representation of this
+ * <code>IssuerAndSerial</code> object.
+ *
+ * @return The <code>String</code> representation.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return ("(IssuerAndSerial - Issuer<" + getIssuerDN())
+ + ("> Serial<" + serial.toString() + ">)");
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/data/SAMLStatus.java b/id.server/src/at/gv/egovernment/moa/id/data/SAMLStatus.java
new file mode 100644
index 000000000..ed61827b6
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/data/SAMLStatus.java
@@ -0,0 +1,59 @@
+package at.gv.egovernment.moa.id.data;
+
+/**
+ * Data contained in a <code>&lt;samlp:Status&gt;</code>
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class SAMLStatus {
+
+ /** main status code */
+ private String statusCode;
+ /** sub status code */
+ private String subStatusCode;
+ /** status message */
+ private String statusMessage;
+
+ /**
+ * @return status code
+ */
+ public String getStatusCode() {
+ return statusCode;
+ }
+
+ /**
+ * @return status message
+ */
+ public String getStatusMessage() {
+ return statusMessage;
+ }
+
+ /**
+ * @return enclosed sub-status code
+ */
+ public String getSubStatusCode() {
+ return subStatusCode;
+ }
+
+ /**
+ * @param string the status code
+ */
+ public void setStatusCode(String string) {
+ statusCode = string;
+ }
+
+ /**
+ * @param string the status message
+ */
+ public void setStatusMessage(String string) {
+ statusMessage = string;
+ }
+
+ /**
+ * @param string the enclosed sub-status code
+ */
+ public void setSubStatusCode(String string) {
+ subStatusCode = string;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/iaik/config/CertStoreConfigurationImpl.java b/id.server/src/at/gv/egovernment/moa/id/iaik/config/CertStoreConfigurationImpl.java
new file mode 100644
index 000000000..421286876
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/iaik/config/CertStoreConfigurationImpl.java
@@ -0,0 +1,91 @@
+package at.gv.egovernment.moa.id.iaik.config;
+
+import java.io.File;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConfigurationProvider;
+import at.gv.egovernment.moa.id.iaik.servertools.observer.ObservableImpl;
+import iaik.pki.store.certstore.CertStoreConfiguration;
+import iaik.pki.store.certstore.CertStoreParameters;
+import iaik.pki.store.certstore.CertStoreTypes;
+import iaik.pki.store.certstore.directory.DirectoryCertStoreParameters;
+
+/**
+ * Implementation of interface needed to initialize an IAIK JSSE <code>TrustManager</code>
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class CertStoreConfigurationImpl extends ObservableImpl
+ implements CertStoreConfiguration, DirectoryCertStoreParameters {
+ /** identifies the rootDirectory */
+ private String rootDirectory;
+ /** Array for storing all CertStoreParameters */
+ private CertStoreParameters[] parameters;
+
+ /**
+ * Create a new <code>CertStoreConfigurationImpl</code>.
+ *
+ * @param conf The MOA configuration from which the configuration data is
+ * @throws ConfigurationException an any config-error
+ * being read.
+ */
+ public CertStoreConfigurationImpl(ConfigurationProvider conf) throws ConfigurationException {
+ String paramName = ConfigurationProvider.DIRECTORY_CERTSTORE_PARAMETER_PROPERTY;
+ String rootDirParam = conf.getGenericConfigurationParameter(paramName);
+ if (rootDirParam == null)
+ throw new ConfigurationException(
+ "config.08", new Object[] {paramName});
+ File f = new File(rootDirParam);
+ if (f.isDirectory())
+ rootDirectory = f.getAbsolutePath();
+ else
+ throw new ConfigurationException(
+ "config.05", new Object[] {paramName});
+
+ parameters = new CertStoreParameters[] { this };
+ }
+
+ /**
+ * @see iaik.pki.store.certstore.CertStoreConfiguration#getParameters()
+ */
+ public CertStoreParameters[] getParameters() {
+ return parameters;
+ }
+
+ /**
+ * @see iaik.pki.store.certstore.directory.DirectoryCertStoreParameters#getRootDirectory()
+ */
+ public String getRootDirectory() {
+ return rootDirectory;
+ }
+
+ /**
+ * @see iaik.pki.store.certstore.directory.DirectoryCertStoreParameters#createNew()
+ */
+ public boolean createNew() {
+ return false;
+ }
+
+ /**
+ * @see iaik.pki.store.certstore.CertStoreParameters#getId()
+ */
+ public String getId() {
+ return "MOA ID Directory CertStore";
+ }
+
+ /**
+ * @see iaik.pki.store.certstore.CertStoreParameters#isReadOnly()
+ */
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ /**
+ * @return <code>CertStoreTypes.DIRECTORY</code>
+ * @see iaik.pki.store.certstore.CertStoreParameters#getType()
+ */
+ public String getType() {
+ return CertStoreTypes.DIRECTORY;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/iaik/config/LoggerConfigImpl.java b/id.server/src/at/gv/egovernment/moa/id/iaik/config/LoggerConfigImpl.java
new file mode 100644
index 000000000..3cd02a2b5
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/iaik/config/LoggerConfigImpl.java
@@ -0,0 +1,51 @@
+package at.gv.egovernment.moa.id.iaik.config;
+
+import iaik.logging.LogConfigurationException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Properties;
+
+/**
+ * Implementation of interface <needed to initialize an IAIK JSSE <code>TrustManager</code>
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class LoggerConfigImpl implements iaik.logging.LoggerConfig {
+
+ /** logging properties **/
+ private Properties loggingProperties;
+
+ /**
+ * Constructor
+ */
+ public LoggerConfigImpl(String propertyFileURL) throws IOException {
+ InputStream in = new URL(propertyFileURL).openStream();
+ loggingProperties = new Properties();
+ loggingProperties.load(in);
+ in.close();
+ }
+
+ /**
+ * @see iaik.logging.LoggerConfig#getFactory()
+ */
+ public String getFactory() {
+ return "iaik.logging.impl.Log4jFactory";
+ }
+
+ /**
+ * @see iaik.logging.LoggerConfig#getProperties()
+ */
+ public Properties getProperties() throws LogConfigurationException {
+ return loggingProperties;
+ }
+
+ /**
+ * @see iaik.logging.LoggerConfig#getNodeId()
+ */
+ public String getNodeId() {
+ return "iaik";
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/iaik/config/PKIConfigurationImpl.java b/id.server/src/at/gv/egovernment/moa/id/iaik/config/PKIConfigurationImpl.java
new file mode 100644
index 000000000..8d09e2bc9
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/iaik/config/PKIConfigurationImpl.java
@@ -0,0 +1,65 @@
+package at.gv.egovernment.moa.id.iaik.config;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConfigurationProvider;
+import iaik.pki.PKIConfiguration;
+import iaik.pki.pathvalidation.ValidationConfiguration;
+import iaik.pki.revocation.RevocationConfiguration;
+import iaik.pki.store.certstore.CertStoreConfiguration;
+import iaik.pki.store.revocation.archive.ArchiveConfiguration;
+
+/**
+ * Implementation of interface <code>PKIConfiguration</code> needed to
+ * initialize an IAIK JSSE <code>TrustManager</code>
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class PKIConfigurationImpl implements PKIConfiguration {
+ /** The configuration for the CertStore */
+ private CertStoreConfiguration certStoreConfiguration;
+ /** The configuration for the RevocationChecks */
+ private RevocationConfiguration revocationConfiguration;
+ /** The configuration for the Validation */
+ private ValidationConfiguration validationConfiguration;
+
+ /**
+ * Constructor
+ * @param conf the Configuration for the PKIConfig
+ * @throws ConfigurationException for any config error
+ */
+ public PKIConfigurationImpl(ConfigurationProvider conf) throws ConfigurationException {
+ certStoreConfiguration = new CertStoreConfigurationImpl(conf);
+ revocationConfiguration = new RevocationConfigurationImpl();
+ validationConfiguration = new ValidationConfigurationImpl(conf);
+ }
+
+ /**
+ * @see iaik.pki.PKIConfiguration#getCertStoreConfiguration()
+ */
+ public CertStoreConfiguration getCertStoreConfiguration() {
+ return certStoreConfiguration;
+ }
+
+ /**
+ * @see iaik.pki.PKIConfiguration#getRevocationConfiguration()
+ */
+ public RevocationConfiguration getRevocationConfiguration() {
+ return revocationConfiguration;
+ }
+
+ /**
+ * @see iaik.pki.PKIConfiguration#getArchiveConfiguration()
+ */
+ public ArchiveConfiguration getArchiveConfiguration() {
+ return null;
+ }
+
+ /**
+ * @see iaik.pki.PKIConfiguration#getValidationConfiguration()
+ */
+ public ValidationConfiguration getValidationConfiguration() {
+ return validationConfiguration;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/iaik/config/RevocationConfigurationImpl.java b/id.server/src/at/gv/egovernment/moa/id/iaik/config/RevocationConfigurationImpl.java
new file mode 100644
index 000000000..c583babdc
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/iaik/config/RevocationConfigurationImpl.java
@@ -0,0 +1,35 @@
+package at.gv.egovernment.moa.id.iaik.config;
+
+import iaik.pki.revocation.RevocationConfiguration;
+
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Set;
+
+import at.gv.egovernment.moa.id.iaik.servertools.observer.*;
+
+/**
+ * Implementation of interface needed to initialize an IAIK JSSE <code>TrustManager</code>
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class RevocationConfigurationImpl extends ObservableImpl implements RevocationConfiguration {
+
+ /**
+ * @see iaik.pki.revocation.RevocationConfiguration#getAlternativeDistributionPoints(java.security.cert.X509Certificate, java.util.Date)
+ */
+ public Set getAlternativeDistributionPoints(
+ X509Certificate arg0,
+ Date arg1) {
+ return Collections.EMPTY_SET;
+ }
+
+ /**
+ * @see iaik.pki.revocation.RevocationConfiguration#archiveRevocationInfo(java.lang.String, java.lang.String)
+ */
+ public boolean archiveRevocationInfo(String arg0, String arg1) {
+ return false;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/iaik/config/ValidationConfigurationImpl.java b/id.server/src/at/gv/egovernment/moa/id/iaik/config/ValidationConfigurationImpl.java
new file mode 100644
index 000000000..c500e2e8e
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/iaik/config/ValidationConfigurationImpl.java
@@ -0,0 +1,51 @@
+package at.gv.egovernment.moa.id.iaik.config;
+
+import iaik.pki.pathvalidation.ValidationConfiguration;
+
+import java.security.cert.X509Certificate;
+import java.security.spec.AlgorithmParameterSpec;
+
+import at.gv.egovernment.moa.id.config.ConfigurationProvider;
+import at.gv.egovernment.moa.id.iaik.servertools.observer.ObservableImpl;
+
+/**
+ * Implementation of interface needed to initialize an IAIK JSSE <code>TrustManager</code>
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ValidationConfigurationImpl extends ObservableImpl
+ implements ValidationConfiguration {
+ /** The ConfigurationProvider for the validation*/
+ private ConfigurationProvider conf;
+
+ /**
+ * Constructor
+ * @param conf with the configuration
+ */
+ public ValidationConfigurationImpl(ConfigurationProvider conf) {
+ this.conf = conf;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationConfiguration#getChainingMode(java.security.cert.X509Certificate)
+ */
+ public String getChainingMode(X509Certificate trustAnchor) {
+ String chainingMode = conf.getChainingMode(trustAnchor);
+ return chainingMode;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationConfiguration#getPublicKeyParamsAsSpec(java.security.cert.X509Certificate)
+ */
+ public AlgorithmParameterSpec getPublicKeyParamsAsSpec(X509Certificate arg0) {
+ return null;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationConfiguration#getPublicKeyParamsAsCert(java.security.cert.X509Certificate)
+ */
+ public X509Certificate getPublicKeyParamsAsCert(X509Certificate arg0) {
+ return null;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/iaik/pki/PKIProfileImpl.java b/id.server/src/at/gv/egovernment/moa/id/iaik/pki/PKIProfileImpl.java
new file mode 100644
index 000000000..882a9c255
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/iaik/pki/PKIProfileImpl.java
@@ -0,0 +1,159 @@
+package at.gv.egovernment.moa.id.iaik.pki;
+
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.Set;
+
+import iaik.pki.PKIProfile;
+import iaik.pki.pathvalidation.ValidationProfile;
+import iaik.pki.revocation.RevocationProfile;
+import iaik.pki.revocation.RevocationSourceTypes;
+import iaik.pki.store.truststore.TrustStoreProfile;
+import iaik.pki.store.truststore.TrustStoreTypes;
+
+import at.gv.egovernment.moa.id.iaik.servertools.observer.ObservableImpl;
+
+/**
+ * Implementation of the <code>PKIProfile</code> interface and subinterfaces
+ * providing information needed for certificate path validation.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class PKIProfileImpl extends ObservableImpl
+ implements PKIProfile, RevocationProfile, TrustStoreProfile, ValidationProfile {
+
+ /**
+ * URI to the truststore
+ */
+ private String trustStoreURI;
+
+ /**
+ * Create a new <code>PKIProfileImpl</code>.
+ *
+ * @param trustStoreURI trust store URI
+ */
+ public PKIProfileImpl(String trustStoreURI) {
+ this.trustStoreURI = trustStoreURI;
+ }
+
+ /**
+ * @see iaik.pki.PKIProfile#autoAddCertificates()
+ */
+ public boolean autoAddCertificates() {
+ return true;
+ }
+
+ /**
+ * @see iaik.pki.PKIProfile#getRevocationProfile()
+ */
+ public RevocationProfile getRevocationProfile() {
+ return this;
+ }
+
+ /**
+ * @see iaik.pki.PKIProfile#getTrustStoreProfile()
+ */
+ public TrustStoreProfile getTrustStoreProfile() {
+ return this;
+ }
+
+ /**
+ * @see iaik.pki.PKIProfile#getValidationProfile()
+ */
+ public ValidationProfile getValidationProfile() {
+ return this;
+ }
+
+ /**
+ * @see iaik.pki.PKIProfile#useAuthorityInfoAccess()
+ */
+ public boolean useAuthorityInfoAccess() {
+ return true;
+ }
+
+ /**
+ * @see iaik.pki.revocation.RevocationProfile#getMaxRevocationAge(java.lang.String)
+ */
+ public long getMaxRevocationAge(String arg0) {
+ return 0;
+ }
+
+ /**
+ * @see iaik.pki.revocation.RevocationProfile#getOCSPRequestHashAlgorithm()
+ */
+ public String getOCSPRequestHashAlgorithm() {
+ return null;
+ }
+
+ /**
+ * @see iaik.pki.revocation.RevocationProfile#getPreferredServiceOrder(java.security.cert.X509Certificate)
+ */
+ public String[] getPreferredServiceOrder(X509Certificate arg0) {
+ return new String[] {RevocationSourceTypes.CRL};
+ }
+
+ /**
+ * @see iaik.pki.store.truststore.TrustStoreProfile#getType()
+ */
+ public String getType() {
+ return TrustStoreTypes.DIRECTORY;
+ }
+
+ /**
+ * @see iaik.pki.store.truststore.TrustStoreProfile#getURI()
+ */
+ public String getURI() {
+ return trustStoreURI;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationProfile#getInitialAnyPolicyInhibit()
+ */
+ public boolean getInitialAnyPolicyInhibit() {
+ return false;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationProfile#getInitialExplicitPolicy()
+ */
+ public boolean getInitialExplicitPolicy() {
+ return false;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationProfile#getInitialPolicyMappingInhibit()
+ */
+ public boolean getInitialPolicyMappingInhibit() {
+ return false;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationProfile#getInitialPolicySet()
+ */
+ public Set getInitialPolicySet() {
+ return Collections.EMPTY_SET;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationProfile#getNameConstraintsProcessing()
+ */
+ public boolean getNameConstraintsProcessing() {
+ return false;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationProfile#getPolicyProcessing()
+ */
+ public boolean getPolicyProcessing() {
+ return false;
+ }
+
+ /**
+ * @see iaik.pki.pathvalidation.ValidationProfile#getRevocationChecking()
+ */
+ public boolean getRevocationChecking() {
+ return true;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/iaik/pki/jsse/MOAIDTrustManager.java b/id.server/src/at/gv/egovernment/moa/id/iaik/pki/jsse/MOAIDTrustManager.java
new file mode 100644
index 000000000..9da006d35
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/iaik/pki/jsse/MOAIDTrustManager.java
@@ -0,0 +1,119 @@
+package at.gv.egovernment.moa.id.iaik.pki.jsse;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.logging.LoggingContext;
+import at.gv.egovernment.moa.logging.LoggingContextManager;
+
+import iaik.pki.jsse.IAIKX509TrustManager;
+
+/**
+ * <code>TrustManager</code> implementation featuring CRL checking (inherited from
+ * <code>IAIKX509TrustManager</code>), plus server-end-SSL-certificate checking.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class MOAIDTrustManager extends IAIKX509TrustManager {
+
+ /** an x509Certificate array containing all accepted server certificates*/
+ private X509Certificate[] acceptedServerCertificates;
+
+ /**
+ * Constructor
+ * @param acceptedServerCertificateStoreURL the url leading to the acceptedServer cert store
+ * @throws GeneralSecurityException occurs on security errors
+ * @throws IOException occurs on IO errors
+ */
+ public MOAIDTrustManager(String acceptedServerCertificateStoreURL)
+ throws IOException, GeneralSecurityException {
+
+ if (acceptedServerCertificateStoreURL != null)
+ buildAcceptedServerCertificates(acceptedServerCertificateStoreURL);
+ else
+ acceptedServerCertificates = null;
+ }
+
+
+ /**
+ * Initializes the LoggingContextManager logging context.
+ * Fixes a bug occuring in the case MOA-SP is called by API.
+ * In this case, IAIKX509TrustManager uses the LogginConfig of MOA-SP.
+ * This method must be called before a MOAIDTrustManager is constructed,
+ * from every thread.
+ */
+ public static void initializeLoggingContext() {
+ if (LoggingContextManager.getInstance().getLoggingContext() == null)
+ LoggingContextManager.getInstance().setLoggingContext(
+ new LoggingContext(Thread.currentThread().getName()));
+ }
+
+
+ /**
+ * Builds an Array of accepted server certificates from an URL,
+ * and stores it in <code>acceptedServerCertificates</code>.
+ * @param acceptedServerCertificateStoreURL file URL pointing to the directory
+ * containing accepted server X509 certificates
+ * @throws GeneralSecurityException on security errors
+ * @throws IOException on any IO errors
+ */
+ private void buildAcceptedServerCertificates(String acceptedServerCertificateStoreURL)
+ throws IOException, GeneralSecurityException {
+
+ List certList = new ArrayList();
+ URL storeURL = new URL(acceptedServerCertificateStoreURL);
+ File storeDir = new File(storeURL.getFile());
+ // list certificate files in directory
+ File[] certFiles = storeDir.listFiles();
+ for (int i = 0; i < certFiles.length; i++) {
+ // for each: create an X509Certificate and store it in list
+ File certFile = certFiles[i];
+ FileInputStream fis = new FileInputStream(certFile.getPath());
+ CertificateFactory certFact = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate)certFact.generateCertificate(fis);
+ fis.close();
+ certList.add(cert);
+ }
+ // store acceptedServerCertificates
+ acceptedServerCertificates = (X509Certificate[]) certList.toArray(new X509Certificate[0]);
+ }
+
+ /**
+ * Does additional server-end-SSL-certificate checking.
+ * @see com.sun.net.ssl.X509TrustManager#isServerTrusted(java.security.cert.X509Certificate[])
+ */
+ public boolean isServerTrusted(X509Certificate[] certChain) {
+ boolean trusted = super.isServerTrusted(certChain);
+ if (! trusted || acceptedServerCertificates == null)
+ return trusted;
+ else {
+ // check server-end-SSL-certificate with acceptedServerCertificates
+ X509Certificate serverCert = certChain[0];
+ for (int i = 0; i < acceptedServerCertificates.length; i++) {
+ X509Certificate acceptedServerCert = acceptedServerCertificates[i];
+ if (serverCert.equals(acceptedServerCert))
+ return true;
+ }
+ Logger.warn(MOAIDMessageProvider.getInstance().getMessage("ssl.01", null));
+ return false;
+ }
+ }
+ /**
+ * In rare cases, this method is being called although it should not be.
+ * @see com.sun.net.ssl.X509TrustManager#isClientTrusted(X509Certificate[])
+ */
+ public boolean isClientTrusted(java.security.cert.X509Certificate arg0[])
+ {
+ return true;
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/iaik/servertools/observer/ObservableImpl.java b/id.server/src/at/gv/egovernment/moa/id/iaik/servertools/observer/ObservableImpl.java
new file mode 100644
index 000000000..6f6949ad6
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/iaik/servertools/observer/ObservableImpl.java
@@ -0,0 +1,46 @@
+package at.gv.egovernment.moa.id.iaik.servertools.observer;
+
+import iaik.servertools.observer.NotificationData;
+import iaik.servertools.observer.Observable;
+import iaik.servertools.observer.Observer;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * Implementation of interface <needed to initialize an IAIK JSSE <code>TrustManager</code>
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ObservableImpl implements Observable {
+ /** a List for all observers */
+ private List observers = new ArrayList();
+
+ /**
+ * @see iaik.servertools.observer.Observable#addObserver(iaik.servertools.observer.Observable)
+ */
+ public void addObserver(Observer observer) {
+ observers.add(observer);
+ }
+
+ /**
+ * @see iaik.servertools.observer.Observable#removeObserver(iaik.servertools.observer.Observable)
+ */
+ public boolean removeObserver(Observer observer) {
+ return observers.remove(observer);
+ }
+
+ /**
+ * @see iaik.servertools.observer.Observable#notify(iaik.servertools.observer.NotificationData)
+ */
+ public void notify(NotificationData data) {
+ Iterator iter = observers.iterator();
+ for (iter = observers.iterator(); iter.hasNext();) {
+ Observer observer = (Observer) iter.next();
+ observer.notify(data);
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/ConnectionBuilder.java b/id.server/src/at/gv/egovernment/moa/id/proxy/ConnectionBuilder.java
new file mode 100644
index 000000000..8039b67a6
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/ConnectionBuilder.java
@@ -0,0 +1,54 @@
+package at.gv.egovernment.moa.id.proxy;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.Map;
+
+import javax.net.ssl.SSLSocketFactory;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Builder for {@link java.net.URLConnection} objects used to forward requests
+ * to the remote online application.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+
+public interface ConnectionBuilder {
+
+ /**
+ * Builds an HttpURLConnection to a {@link java.net.URL} which is derived
+ * from an {@link HttpServletRequest} URL, by substitution of a
+ * public URL prefix for the real URL prefix.<br>
+ * The HttpURLConnection has been created by {@link java.net.URL#openConnection}, but
+ * it has not yet been connected to by {@link java.net.URLConnection#connect}.<br>
+ * The field settings of the HttpURLConnection are:
+ * <ul>
+ * <li><code>allowUserInteraction = false</code></li>
+ * <li><code>doInput = true</code></li>
+ * <li><code>doOutput = true</code></li>
+ * <li><code>requestMethod = request.getMethod()</code></li>
+ * <li><code>useCaches = false</code></li>
+ * </ul>
+ *
+ * @param request the incoming request which shall be forwarded
+ * @param publicURLPrefix the public URL prefix to be substituted by the real URL prefix
+ * @param realURLPrefix the URL prefix to substitute the public URL prefix
+ * @param sslSocketFactory factory to be used for creating an SSL socket in case
+ * of a URL for scheme <code>"https:"</code>;
+ * <br>if <code>null</code>, the default SSL socket factory would be used
+ * @param parameters parameters to be forwarded
+ * @return a URLConnection created by {@link java.net.URL#openConnection}, connecting to
+ * the requested URL with <code>publicURLPrefix</code> substituted by <code>realURLPrefix</code>
+ * @throws IOException if an I/O exception occurs during opening the connection
+ * @see java.net.URL#openConnection()
+ * @see com.sun.net.ssl.HttpsURLConnection#getDefaultSSLSocketFactory()
+ */
+ public HttpURLConnection buildConnection(
+ HttpServletRequest request,
+ String publicURLPrefix,
+ String realURLPrefix,
+ SSLSocketFactory sslSocketFactory,
+ Map parameters) throws IOException;
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/ConnectionBuilderFactory.java b/id.server/src/at/gv/egovernment/moa/id/proxy/ConnectionBuilderFactory.java
new file mode 100644
index 000000000..7a6c3e575
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/ConnectionBuilderFactory.java
@@ -0,0 +1,68 @@
+package at.gv.egovernment.moa.id.proxy;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.proxy.ProxyConfigurationProvider;
+import at.gv.egovernment.moa.id.config.proxy.OAProxyParameter;
+
+/**
+ * Factory delivering a {@link ConnectionBuilder} implementation for
+ * an online application, initialized from configuration data.
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ConnectionBuilderFactory {
+
+ /** default connection builder to be used for online application
+ * where no special implementation of the <code>ConnectionBuilder</code>
+ * interface is configured
+ */
+ private static ConnectionBuilder defaultConnectionBuilder;
+ /** mapping from online application public URL prefix to an implementation
+ * of the <code>ConnectionBuilder</code> interface to be used;
+ * if no mapping is given for an online application, the
+ * <code>DefaultConnectionBuilder</code> will be used */
+ private static Map connectionBuilderMap;
+
+ /**
+ * Initializes the <code>ConnectionBuilder</code> map from the configuration data.
+ * @throws ConfigurationException when the configuration cannot be read,
+ * or when a class name configured cannot be instantiated
+ */
+ public static void initialize() throws ConfigurationException {
+ defaultConnectionBuilder = new DefaultConnectionBuilder();
+ connectionBuilderMap = new HashMap();
+ ProxyConfigurationProvider proxyConf = ProxyConfigurationProvider.getInstance();
+ for (int i = 0; i < proxyConf.getOnlineApplicationParameters().length; i++) {
+ OAProxyParameter oaParam = proxyConf.getOnlineApplicationParameters()[i];
+ String publicURLPrefix = oaParam.getPublicURLPrefix();
+ String className = oaParam.getConnectionBuilderImpl();
+ if (className != null) {
+ try {
+ ConnectionBuilder cb = (ConnectionBuilder)Class.forName(className).newInstance();
+ connectionBuilderMap.put(publicURLPrefix, cb);
+ }
+ catch (Throwable ex) {
+ throw new ConfigurationException("config.07", new Object[] {publicURLPrefix}, ex);
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the <code>ConnectionBuilder</code> implementation to be used for the given
+ * online application.
+ * @param publicURLPrefix public URL prefix of the online application
+ * @return <code>ConnectionBuilder</code> implementation
+ */
+ public static ConnectionBuilder getConnectionBuilder(String publicURLPrefix) {
+ ConnectionBuilder cb = (ConnectionBuilder) connectionBuilderMap.get(publicURLPrefix);
+ if (cb == null)
+ return defaultConnectionBuilder;
+ else
+ return cb;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/DefaultConnectionBuilder.java b/id.server/src/at/gv/egovernment/moa/id/proxy/DefaultConnectionBuilder.java
new file mode 100644
index 000000000..48e21f673
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/DefaultConnectionBuilder.java
@@ -0,0 +1,119 @@
+package at.gv.egovernment.moa.id.proxy;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.net.ssl.SSLSocketFactory;
+import javax.servlet.http.HttpServletRequest;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.proxy.ProxyConfigurationProvider;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.BoolUtils;
+
+import com.sun.net.ssl.HostnameVerifier;
+import com.sun.net.ssl.HttpsURLConnection;
+
+/**
+ * Defaultimplementierung von <code>ConnectionBuilder</code>.
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class DefaultConnectionBuilder implements ConnectionBuilder {
+
+ /** a boolean to disable the HostnameVerification (default = false)*/
+ private static boolean disableHostnameVerification = false;
+
+ /**
+ * Constructor for DefaultConnectionBuilder.
+ * @throws ConfigurationException on any config error
+ */
+ public DefaultConnectionBuilder() throws ConfigurationException {
+ disableHostnameVerification = BoolUtils.valueOf(
+ ProxyConfigurationProvider.getInstance().getGenericConfigurationParameter(
+ "ProxyComponent.DisableHostnameVerification"));
+ if (disableHostnameVerification)
+ Logger.warn("ProxyComponent.DisableHostnameVerification: " + disableHostnameVerification);
+ }
+
+ /**
+ * @see at.gv.egovernment.moa.id.proxy.ConnectionBuilder#buildConnection
+ */
+ public HttpURLConnection buildConnection(
+ HttpServletRequest req,
+ String publicURLPrefix,
+ String realURLPrefix,
+ SSLSocketFactory sslSocketFactory,
+ Map parameters)
+ throws IOException {
+
+ String requestedURL = req.getRequestURL().toString();
+ // check whether requested URL starts with publicURLPrefix
+ if (! requestedURL.startsWith(publicURLPrefix))
+ throw new IOException(MOAIDMessageProvider.getInstance().getMessage(
+ "proxy.01", new Object[] {requestedURL, publicURLPrefix}));
+ // in case of GET request, append query string to requested URL;
+ // otherwise, HttpURLConnection would perform a POST request
+ if ("get".equalsIgnoreCase(req.getMethod()) && ! parameters.isEmpty()) {
+ requestedURL = appendQueryString(requestedURL, parameters);
+ }
+ // build real URL in online application
+ String realURLString = realURLPrefix + requestedURL.substring(publicURLPrefix.length());
+ URL url = new URL(realURLString);
+ Logger.debug("OA Request: " + req.getMethod() + " " + url.toString());
+
+ HttpURLConnection conn = (HttpURLConnection)url.openConnection();
+ conn.setRequestMethod(req.getMethod());
+ conn.setDoInput(true);
+ conn.setDoOutput(true);
+ //conn.setUseCaches(false);
+ conn.setAllowUserInteraction(true);
+ conn.setInstanceFollowRedirects(false);
+ if (conn instanceof HttpsURLConnection && sslSocketFactory != null) {
+ HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
+ httpsConn.setSSLSocketFactory(sslSocketFactory);
+ if (disableHostnameVerification)
+ httpsConn.setHostnameVerifier(new HostnameNonVerifier());
+ }
+ return conn;
+ }
+ /**
+ * @param requestedURL
+ * @param parameters
+ * @return
+ */
+ private String appendQueryString(String requestedURL, Map parameters) {
+ String newURL = requestedURL;
+ for (Iterator iter = parameters.keySet().iterator(); iter.hasNext();) {
+ String paramName = (String)iter.next();
+ String paramValue = (String)parameters.get(paramName);
+ String paramString = paramName + "=" + paramValue;
+ if (newURL.indexOf("?") < 0)
+ newURL = newURL + "?" + paramString;
+ else
+ newURL = newURL + "&" + paramString;
+ }
+ return newURL;
+ }
+
+ /**
+ * @author Stefan Knirsch
+ * @version $Id$
+ * A private class to change the standard HostName verifier to disable the
+ * Hostname Verification Check
+ */
+ private class HostnameNonVerifier implements HostnameVerifier {
+
+ /**
+ * @see com.sun.net.ssl.HostnameVerifier#verify(String, String)
+ */
+ public boolean verify(String arg0, String arg1) {
+ return true;
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/DefaultLoginParameterResolver.java b/id.server/src/at/gv/egovernment/moa/id/proxy/DefaultLoginParameterResolver.java
new file mode 100644
index 000000000..db3c452bc
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/DefaultLoginParameterResolver.java
@@ -0,0 +1,118 @@
+package at.gv.egovernment.moa.id.proxy;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import at.gv.egovernment.moa.id.config.proxy.OAConfiguration;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+import at.gv.egovernment.moa.util.Base64Utils;
+
+/**
+ * Implementation of interface <code>LoginParameterResolver</code>
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class DefaultLoginParameterResolver implements LoginParameterResolver {
+
+ /**
+ * Constructor
+ */
+ public DefaultLoginParameterResolver() {
+ }
+
+ /**
+ * @see at.gv.egovernment.moa.id.proxy.LoginParameterResolver#getAuthenticationHeaders(at.gv.egovernment.moa.id.config.proxy.OAConfiguration, at.gv.egovernment.moa.id.auth.data.AuthenticationData, java.lang.String)
+ */
+ public Map getAuthenticationHeaders(
+ OAConfiguration oaConf,
+ AuthenticationData authData,
+ String clientIPAddress) {
+
+ Map result = new HashMap();
+
+ if (oaConf.getAuthType().equals(OAConfiguration.BASIC_AUTH)) {
+ String useridPredicate = oaConf.getBasicAuthUserIDMapping();
+ String userid = resolveValue(useridPredicate, authData, clientIPAddress);
+ String passwordPredicate = oaConf.getBasicAuthPasswordMapping();
+ String password = resolveValue(passwordPredicate, authData, clientIPAddress);
+
+ try {
+ String userIDPassword = userid + ":" + password;
+ String credentials = Base64Utils.encode(userIDPassword.getBytes());
+ result.put("Authorization", "Basic " + credentials);
+ }
+ catch (IOException ignore) {
+ }
+ }
+ else if (oaConf.getAuthType().equals(OAConfiguration.HEADER_AUTH)) {
+ for (Iterator iter = oaConf.getHeaderAuthMapping().keySet().iterator(); iter.hasNext();) {
+ String key = (String) iter.next();
+ String predicate = (String) oaConf.getHeaderAuthMapping().get(key);
+ String resolvedValue = resolveValue(predicate, authData, clientIPAddress);
+ result.put(key, resolvedValue);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * @see at.gv.egovernment.moa.id.proxy.LoginParameterResolver#getAuthenticationParameters(at.gv.egovernment.moa.id.config.proxy.OAConfiguration, at.gv.egovernment.moa.id.auth.data.AuthenticationData, java.lang.String)
+ */
+ public Map getAuthenticationParameters(
+ OAConfiguration oaConf,
+ AuthenticationData authData,
+ String clientIPAddress) {
+
+ Map result = new HashMap();
+
+ if (oaConf.getAuthType().equals(OAConfiguration.PARAM_AUTH)) {
+ for (Iterator iter = oaConf.getParamAuthMapping().keySet().iterator(); iter.hasNext();) {
+ String key = (String) iter.next();
+ String predicate = (String) oaConf.getParamAuthMapping().get(key);
+ String resolvedValue = resolveValue(predicate, authData, clientIPAddress);
+ result.put(key, resolvedValue);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Resolves a login header or parameter value.
+ * @param predicate header or parameter predicate name from online application configuration
+ * @param authData authentication data for current login
+ * @param clientIPAddress client IP address
+ * @return header or parameter value resolved; <code>null</code> if unknown name is given
+ */
+ private static String resolveValue(String predicate, AuthenticationData authData, String clientIPAddress) {
+ if (predicate.equals(MOAGivenName))
+ return authData.getGivenName();
+ else if (predicate.equals(MOAFamilyName))
+ return authData.getFamilyName();
+ else if (predicate.equals(MOADateOfBirth))
+ return authData.getDateOfBirth();
+ else if (predicate.equals(MOAVPK))
+ return authData.getVPK();
+ else if (predicate.equals(MOAPublicAuthority))
+ if (authData.isPublicAuthority())
+ return "true";
+ else
+ return "false";
+ else if (predicate.equals(MOABKZ))
+ return authData.getPublicAuthorityCode();
+ else if (predicate.equals(MOAQualifiedCertificate))
+ if (authData.isQualifiedCertificate())
+ return "true";
+ else
+ return "false";
+ else if (predicate.equals(MOAZMRZahl))
+ return authData.getIdentificationValue();
+ else if (predicate.equals(MOAIPAddress))
+ return clientIPAddress;
+ else return null;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/LoginParameterResolver.java b/id.server/src/at/gv/egovernment/moa/id/proxy/LoginParameterResolver.java
new file mode 100644
index 000000000..497176a96
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/LoginParameterResolver.java
@@ -0,0 +1,72 @@
+package at.gv.egovernment.moa.id.proxy;
+
+import java.util.Map;
+
+import at.gv.egovernment.moa.id.config.proxy.OAConfiguration;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+
+/**
+ * Determines authentication parameters and headers to be added to a {@link java.net.URLConnection}
+ * to the remote online application.
+ * Utilizes {@link OAConfiguration} and {@link AuthenticationData}.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public interface LoginParameterResolver {
+
+ /** Constants used in <code>MOAIDConfiguration-1.1.xsd</code>, type <code>MOAAuthDataType</code>,
+ * naming predicates used by the <code>LoginParameterResolver</code>. */
+ public static final String MOAGivenName = "MOAGivenName";
+ /** Constant used in <code>MOAIDConfiguration-1.1.xsd</code>, type <code>MOAAuthDataType</code> */
+ public static final String MOAFamilyName = "MOAFamilyName";
+ /** Constant used in <code>MOAIDConfiguration-1.1.xsd</code>, type <code>MOAAuthDataType</code> */
+ public static final String MOADateOfBirth = "MOADateOfBirth";
+ /** Constant used in <code>MOAIDConfiguration-1.1.xsd</code>, type <code>MOAAuthDataType</code> */
+ public static final String MOAVPK = "MOAVPK";
+ /** Constant used in <code>MOAIDConfiguration-1.1.xsd</code>, type <code>MOAAuthDataType</code> */
+ public static final String MOAPublicAuthority = "MOAPublicAuthority";
+ /** Constant used in <code>MOAIDConfiguration-1.1.xsd</code>, type <code>MOAAuthDataType</code> */
+ public static final String MOABKZ = "MOABKZ";
+ /** Constant used in <code>MOAIDConfiguration-1.1.xsd</code>, type <code>MOAAuthDataType</code> */
+ public static final String MOAQualifiedCertificate = "MOAQualifiedCertificate";
+ /** Constant used in <code>MOAIDConfiguration-1.1.xsd</code>, type <code>MOAAuthDataType</code> */
+ public static final String MOAZMRZahl = "MOAZMRZahl";
+ /** Constant used in <code>MOAIDConfiguration-1.1.xsd</code>, type <code>MOAAuthDataType</code> */
+ public static final String MOAIPAddress = "MOAIPAddress";
+
+ /**
+ * Returns authentication headers to be added to a URLConnection.
+ *
+ * @param oaConf configuration data
+ * @param authData authentication data
+ * @param clientIPAddress client IP address
+ * @return A map, the keys being header names and values being corresponding header values.
+ * <br>In case of authentication type <code>"basic-auth"</code>, header fields
+ * <code>username</code> and <code>password</code>.
+ * <br>In case of authentication type <code>"header-auth"</code>, header fields
+ * derived from parameter mapping and authentication data provided.
+ * <br>Otherwise, an empty map.
+ */
+ public Map getAuthenticationHeaders (
+ OAConfiguration oaConf,
+ AuthenticationData authData,
+ String clientIPAddress);
+
+ /**
+ * Returns request parameters to be added to a URLConnection.
+ *
+ * @param oaConf configuration data
+ * @param authData authentication data
+ * @param clientIPAddress client IP address
+ * @return A map, the keys being parameter names and values being corresponding parameter values.
+ * <br>In case of authentication type <code>"param-auth"</code>, parameters
+ * derived from parameter mapping and authentication data provided.
+ * <br>Otherwise, an empty map.
+ */
+ public Map getAuthenticationParameters (
+ OAConfiguration oaConf,
+ AuthenticationData authData,
+ String clientIPAddress);
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/LoginParameterResolverFactory.java b/id.server/src/at/gv/egovernment/moa/id/proxy/LoginParameterResolverFactory.java
new file mode 100644
index 000000000..2ab245923
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/LoginParameterResolverFactory.java
@@ -0,0 +1,68 @@
+package at.gv.egovernment.moa.id.proxy;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.proxy.ProxyConfigurationProvider;
+import at.gv.egovernment.moa.id.config.proxy.OAProxyParameter;
+
+/**
+ * Factory delivering a {@link LoginParameterResolver} implementation for
+ * an online application, initialized from configuration data.
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class LoginParameterResolverFactory {
+
+ /** default login parameter resolver to be used for online application
+ * where no special implementation of the <code>LoginParameterResolver</code>
+ * interface is configured
+ */
+ private static LoginParameterResolver defaultLoginParameterResolver;
+ /** mapping from online application public URL prefix to an implementation
+ * of the <code>LoginParameterResolver</code> interface to be used;
+ * if no mapping is given for an online application, the
+ * <code>DefaultLoginParameterResolver</code> will be used */
+ private static Map loginParameterResolverMap;
+
+ /**
+ * Initializes the <code>LoginParameterResolver</code> map from the configuration data.
+ * @throws ConfigurationException when the configuration cannot be read,
+ * or when a class name configured cannot be instantiated
+ */
+ public static void initialize() throws ConfigurationException {
+ defaultLoginParameterResolver = new DefaultLoginParameterResolver();
+ loginParameterResolverMap = new HashMap();
+ ProxyConfigurationProvider proxyConf = ProxyConfigurationProvider.getInstance();
+ for (int i = 0; i < proxyConf.getOnlineApplicationParameters().length; i++) {
+ OAProxyParameter oaParam = proxyConf.getOnlineApplicationParameters()[i];
+ String publicURLPrefix = oaParam.getPublicURLPrefix();
+ String className = oaParam.getLoginParameterResolverImpl();
+ if (className != null) {
+ try {
+ LoginParameterResolver lpr = (LoginParameterResolver)Class.forName(className).newInstance();
+ loginParameterResolverMap.put(publicURLPrefix, lpr);
+ }
+ catch (Throwable ex) {
+ throw new ConfigurationException("config.07", new Object[] {publicURLPrefix}, ex);
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the <code>LoginParameterResolver</code> implementation to be used for the given
+ * online application.
+ * @param publicURLPrefix public URL prefix of the online application
+ * @return <code>LoginParameterResolver</code> implementation
+ */
+ public static LoginParameterResolver getLoginParameterResolver(String publicURLPrefix) {
+ LoginParameterResolver lpr = (LoginParameterResolver) loginParameterResolverMap.get(publicURLPrefix);
+ if (lpr == null)
+ return defaultLoginParameterResolver;
+ else
+ return lpr;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/MOAIDProxyInitializer.java b/id.server/src/at/gv/egovernment/moa/id/proxy/MOAIDProxyInitializer.java
new file mode 100644
index 000000000..da5d36678
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/MOAIDProxyInitializer.java
@@ -0,0 +1,91 @@
+package at.gv.egovernment.moa.id.proxy;
+
+import iaik.pki.PKIException;
+import iaik.pki.jsse.IAIKX509TrustManager;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import javax.net.ssl.SSLSocketFactory;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.config.proxy.OAProxyParameter;
+import at.gv.egovernment.moa.id.config.proxy.ProxyConfigurationProvider;
+import at.gv.egovernment.moa.id.iaik.config.LoggerConfigImpl;
+import at.gv.egovernment.moa.id.util.AxisSecureSocketFactory;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.id.util.SSLUtils;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Web application initializer
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class MOAIDProxyInitializer {
+
+ /**
+ * Initializes the web application components which need initialization:
+ * logging, JSSE, MOA-ID Auth configuration, Axis, session cleaner.
+ */
+ public static void initialize()
+ throws ConfigurationException, IOException, GeneralSecurityException, PKIException {
+
+ Logger.setHierarchy("moa.id.proxy");
+
+ // Restricts TLS cipher suites
+ System.setProperty("https.cipherSuites", "SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_MD5,SSL_RSA_WITH_3DES_EDE_CBC_SHA");
+
+ // load some jsse classes so that the integrity of the jars can be verified
+ // before the iaik jce is installed as the security provider
+ // this workaround is only needed when sun jsse is used in conjunction with
+ // iaik-jce (on jdk1.3)
+ ClassLoader cl = MOAIDProxyInitializer.class.getClassLoader();
+ try {
+ cl.loadClass("javax.security.cert.Certificate"); // from jcert.jar
+ }
+ catch (ClassNotFoundException e) {
+ Logger.warn(MOAIDMessageProvider.getInstance().getMessage("init.01", null), e);
+ }
+
+ // Initializes the SSLSocketFactory store
+ SSLUtils.initialize();
+
+ // Initializes IAIKX509TrustManager logging
+ String log4jConfigURL = System.getProperty("log4j.configuration");
+ if (log4jConfigURL != null) {
+ IAIKX509TrustManager.initLog(new LoggerConfigImpl(log4jConfigURL));
+ }
+
+ // Loads the configuration
+ ProxyConfigurationProvider proxyConf = ProxyConfigurationProvider.reload();
+
+ // Initializes the Axis secure socket factory for use in calling the MOA-Auth web service,
+ // using configuration data
+ ConnectionParameter connParamAuth = proxyConf.getAuthComponentConnectionParameter();
+ if (connParamAuth.isHTTPSURL()) {
+ SSLSocketFactory ssf = SSLUtils.getSSLSocketFactory(proxyConf, connParamAuth);
+ AxisSecureSocketFactory.initialize(ssf);
+ }
+
+ // Initializes the Axis secure socket factories for use in calling the online applications,
+ // using configuration data
+ OAProxyParameter[] oaParams = proxyConf.getOnlineApplicationParameters();
+ for (int i = 0; i < oaParams.length; i++) {
+ OAProxyParameter oaParam = oaParams[i];
+ ConnectionParameter oaConnParam = oaParam.getConnectionParameter();
+ if (oaConnParam.isHTTPSURL())
+ SSLUtils.getSSLSocketFactory(proxyConf, oaConnParam);
+ }
+
+ // Initializes the ConnectionBuilderFactory from configuration data
+ ConnectionBuilderFactory.initialize();
+
+ // Initializes the LoginParameterResolverFactory from configuration data
+ LoginParameterResolverFactory.initialize();
+
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/WebmailLoginParameterResolver.class b/id.server/src/at/gv/egovernment/moa/id/proxy/WebmailLoginParameterResolver.class
new file mode 100644
index 000000000..49200265a
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/WebmailLoginParameterResolver.class
Binary files differ
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/builder/SAMLRequestBuilder.java b/id.server/src/at/gv/egovernment/moa/id/proxy/builder/SAMLRequestBuilder.java
new file mode 100644
index 000000000..e0e1fde4a
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/builder/SAMLRequestBuilder.java
@@ -0,0 +1,55 @@
+package at.gv.egovernment.moa.id.proxy.builder;
+
+import java.text.MessageFormat;
+import java.util.Calendar;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.BuildException;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.DateTimeUtils;
+
+/**
+ * Builder for the <code>&lt;samlp:Request&gt;</code> used for querying
+ * the authentication data <code>&lt;saml:Assertion&gt;</code>.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class SAMLRequestBuilder implements Constants {
+ /** samlp-Request template */
+ private static final String REQUEST =
+ "<samlp:Request xmlns:samlp=\"urn:oasis:names:tc:SAML:1.0:protocol\" RequestID=\"{0}\" MajorVersion=\"1\" MinorVersion=\"0\" IssueInstant=\"{1}\">" +
+ "<samlp:AssertionArtifact>{2}</samlp:AssertionArtifact>" +
+ "</samlp:Request>";
+
+ /**
+ * Constructor for SAMLRequestBuilder.
+ */
+ public SAMLRequestBuilder() {
+ super();
+ }
+
+ /**
+ * Builds the <code>&lt;samlp:Request&gt;</code>.
+ * @param requestID request ID
+ * @param samlArtifactBase64 SAML artifact, encoded BASE64
+ * @return the DOM element
+ */
+ public Element build(String requestID, String samlArtifactBase64) throws BuildException {
+ try {
+ String issueInstant = DateTimeUtils.buildDateTime(Calendar.getInstance());
+ String request = MessageFormat.format(REQUEST, new Object[] {requestID, issueInstant, samlArtifactBase64});
+ Element requestElem = DOMUtils.parseDocument(request, false, ALL_SCHEMA_LOCATIONS, null).getDocumentElement();
+ return requestElem;
+ }
+ catch (Throwable ex) {
+ throw new BuildException(
+ "builder.00",
+ new Object[] {"samlp:Request", ex.toString()},
+ ex);
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/invoke/GetAuthenticationDataInvoker.java b/id.server/src/at/gv/egovernment/moa/id/proxy/invoke/GetAuthenticationDataInvoker.java
new file mode 100644
index 000000000..4e9a72111
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/invoke/GetAuthenticationDataInvoker.java
@@ -0,0 +1,143 @@
+package at.gv.egovernment.moa.id.proxy.invoke;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Vector;
+
+import javax.xml.namespace.QName;
+import javax.xml.rpc.Call;
+import javax.xml.rpc.Service;
+import javax.xml.rpc.ServiceFactory;
+
+import org.apache.axis.message.SOAPBodyElement;
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.AuthenticationException;
+import at.gv.egovernment.moa.id.BuildException;
+import at.gv.egovernment.moa.id.ParseException;
+import at.gv.egovernment.moa.id.ServiceException;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.config.proxy.ProxyConfigurationProvider;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+import at.gv.egovernment.moa.id.data.SAMLStatus;
+import at.gv.egovernment.moa.id.proxy.builder.SAMLRequestBuilder;
+import at.gv.egovernment.moa.id.proxy.parser.SAMLResponseParser;
+import at.gv.egovernment.moa.id.proxy.servlet.ProxyException;
+import at.gv.egovernment.moa.id.util.Random;
+
+/**
+ * Invoker of
+ * <ul>
+ * <li>either the GetAuthenticationData web service of MOA-ID Auth</li>
+ * <li>or the API call {@link at.gv.egovernment.moa.id.auth.AuthenticationServer#getAuthenticationData},</li>
+ * </ul>
+ * depending of the configuration.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class GetAuthenticationDataInvoker {
+ /** Create a new QName object for the webservice endpoint */
+ private static final QName SERVICE_QNAME = new QName("GetAuthenticationData");
+
+ /** invoked object for API call of MOA-ID Auth */
+ private static Object apiServer = null;
+ /** invoked method for API call of MOA-ID Auth */
+ private static Method apiMethod = null;
+
+ /**
+ * Invokes the service passing domain model objects.
+ * @param samlArtifact SAML artifact
+ * @return AuthenticationData object
+ * @throws ServiceException on any exception thrown
+ */
+ /**
+ * Get authentication data from the MOA-ID Auth component,
+ * either via API call or via web service call.
+ * @param samlArtifact SAML artifact to be used as a parameter
+ * @return AuthenticationData
+ */
+ public AuthenticationData getAuthenticationData(String samlArtifact)
+ throws ConfigurationException, ProxyException, BuildException, ServiceException, ParseException, AuthenticationException {
+
+ ConnectionParameter authConnParam =
+ ProxyConfigurationProvider.getInstance().getAuthComponentConnectionParameter();
+ if (authConnParam == null) {
+ try {
+ if (apiServer == null) {
+ Class serverClass = Class.forName("at.gv.egovernment.moa.id.auth.AuthenticationServer");
+ Method getInstanceMethod = serverClass.getMethod("getInstance", null);
+ apiServer = getInstanceMethod.invoke(null, null);
+ apiMethod = serverClass.getMethod(
+ "getAuthenticationData", new Class[] {String.class});
+ }
+ AuthenticationData authData = (AuthenticationData)apiMethod.invoke(apiServer, new Object[] {samlArtifact});
+ return authData;
+ }
+ catch (InvocationTargetException ex) {
+ Throwable targetEx = ex.getTargetException();
+ if (targetEx instanceof AuthenticationException)
+ throw (AuthenticationException) targetEx;
+ else
+ throw new ProxyException("proxy.09", new Object[] {targetEx.toString()});
+ }
+ catch (Throwable ex) {
+ throw new ProxyException("proxy.09", new Object[] {ex.toString()});
+ }
+ }
+ else {
+ Element samlpRequest = new SAMLRequestBuilder().build(Random.nextRandom(), samlArtifact);
+ Element samlpResponse = getAuthenticationData(samlpRequest);
+ SAMLResponseParser srp = new SAMLResponseParser(samlpResponse);
+ SAMLStatus status = srp.parseStatusCode();
+ if (! "samlp:Success".equals(status.getStatusCode())) {
+ // on error status throw exception
+ String code = status.getStatusCode();
+ if (status.getSubStatusCode() != null && status.getSubStatusCode().length() > 0)
+ code += "(" + status.getSubStatusCode() + ")";
+ throw new ServiceException("service.02", new Object[] {code, status.getStatusMessage()});
+ }
+ return srp.parseAuthenticationData();
+ }
+ }
+
+ /**
+ * Invokes the service passing DOM elements.
+ * @param request request DOM element
+ * @return response DOM element
+ * @throws ServiceException on any exception thrown
+ */
+ public Element getAuthenticationData(Element request) throws ServiceException {
+ try {
+ Service service = ServiceFactory.newInstance().createService(SERVICE_QNAME);
+ Call call = service.createCall();
+ SOAPBodyElement body =
+ new SOAPBodyElement(request);
+ SOAPBodyElement[] params = new SOAPBodyElement[] {body};
+ Vector responses;
+ SOAPBodyElement response;
+
+ String endPoint;
+ ConnectionParameter authConnParam =
+ ProxyConfigurationProvider.getInstance().getAuthComponentConnectionParameter();
+
+ //If the ConnectionParameter do NOT exist, we throw an exception ....
+ if (authConnParam!=null) {
+ endPoint = authConnParam.getUrl();
+ call.setTargetEndpointAddress(endPoint);
+ responses = (Vector) call.invoke(SERVICE_QNAME, params);
+ response = (SOAPBodyElement) responses.get(0);
+ return response.getAsDOM();
+ }
+ else
+ {
+ throw new ServiceException("service.01", null);
+ }
+ }
+ catch (Exception ex) {
+ throw new ServiceException("service.00", new Object[] {ex.toString()}, ex);
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/parser/AuthenticationDataAssertionParser.java b/id.server/src/at/gv/egovernment/moa/id/proxy/parser/AuthenticationDataAssertionParser.java
new file mode 100644
index 000000000..ce0743b3d
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/parser/AuthenticationDataAssertionParser.java
@@ -0,0 +1,145 @@
+package at.gv.egovernment.moa.id.proxy.parser;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.ParseException;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+import at.gv.egovernment.moa.util.BoolUtils;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Parser for the <code>&lt;saml:Assertion&gt;</code> returned by the
+ * <code>GetAuthenticationData</code> web service.
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class AuthenticationDataAssertionParser implements Constants {
+
+ /** Prefix for SAML-Xpath-expressions */
+ private static String SAML = SAML_PREFIX + ":";
+ /** Prefix for PersonData-Xpath-expressions */
+ private static String PR = PD_PREFIX + ":";
+ /** Prefix for Attribute MajorVersion in an Xpath-expression */
+ private static String MAJOR_VERSION_XPATH =
+ "@MajorVersion";
+ /** Prefix for Attribute MinorVersion in an Xpath-expression */
+ private static String MINOR_VERSION_XPATH =
+ "@MinorVersion";
+ /** Prefix for Attribute AssertionID in an Xpath-expression */
+ private static String ASSERTION_ID_XPATH =
+ "@AssertionID";
+ /** Prefix for Attribute Issuer in an Xpath-expression */
+ private static String ISSUER_XPATH =
+ "@Issuer";
+ /** Prefix for Attribute IssueInstant in an Xpath-expression */
+ private static String ISSUE_INSTANT_XPATH =
+ "@IssueInstant";
+ /** Prefix for Element AttributeStatement in an Xpath-expression */
+ private static String ATTRIBUTESTATEMENT_XPATH =
+ SAML + "AttributeStatement/";
+ /** Prefix for Element NameIdentifier in an Xpath-expression */
+ private static String VPK_XPATH =
+ ATTRIBUTESTATEMENT_XPATH +
+ SAML + "Subject/" +
+ SAML + "NameIdentifier";
+ /** Prefix for Element Person in an Xpath-expression */
+ private static String PERSONDATA_XPATH =
+ ATTRIBUTESTATEMENT_XPATH +
+ SAML + "Attribute[@AttributeName=\"PersonData\"]/" +
+ SAML + "AttributeValue/" +
+ PR + "Person/";
+ /** Prefix for Element Value in an Xpath-expression */
+ private static String ZMRZAHL_XPATH =
+ PERSONDATA_XPATH +
+ PR + "Identification/" +
+ PR + "Value";
+ /** Prefix for Element GivenName in an Xpath-expression */
+ private static String GIVEN_NAME_XPATH =
+ PERSONDATA_XPATH +
+ PR + "Name/" +
+ PR + "GivenName";
+ /** Prefix for Element FamilyName in an Xpath-expression */
+ private static String FAMILY_NAME_XPATH =
+ PERSONDATA_XPATH +
+ PR + "Name/" +
+ PR + "FamilyName";
+ /** Prefix for Element DateOfBirth in an Xpath-expression */
+ private static String DATE_OF_BIRTH_XPATH =
+ PERSONDATA_XPATH +
+ PR + "DateOfBirth";
+ /** Prefix for Element AttributeValue in an Xpath-expression */
+ private static String IS_QUALIFIED_CERT_XPATH =
+ ATTRIBUTESTATEMENT_XPATH +
+ SAML + "Attribute[@AttributeName=\"isQualifiedCertificate\"]/" +
+ SAML + "AttributeValue";
+ /** Prefix for Element AttributeValue in an Xpath-expression */
+ private static String PUBLIC_AUTHORITY_XPATH =
+ ATTRIBUTESTATEMENT_XPATH +
+ SAML + "Attribute[@AttributeName=\"isPublicAuthority\"]/" +
+ SAML + "AttributeValue";
+ /** Element samlAssertion represents the SAML:Assertion */
+ private Element samlAssertion;
+
+ /**
+ * Constructor
+ * @param samlAssertion samlpResponse the <code>&lt;samlp:Response&gt;</code> as a DOM element
+ */
+ public AuthenticationDataAssertionParser(Element samlAssertion) {
+ this.samlAssertion = samlAssertion;
+ }
+
+ /**
+ * Parses the <code>&lt;saml:Assertion&gt;</code>.
+ * @return <code>AuthenticationData</code> object
+ * @throws ParseException on any error
+ */
+ public AuthenticationData parseAuthenticationData()
+ throws ParseException {
+
+ try {
+ AuthenticationData authData = new AuthenticationData();
+ //ÄNDERN: NUR der Identification-Teil
+ authData.setSamlAssertion(DOMUtils.serializeNode(samlAssertion));
+ authData.setMajorVersion(new Integer(
+ XPathUtils.getAttributeValue(samlAssertion, MAJOR_VERSION_XPATH, "-1")).intValue());
+ authData.setMinorVersion(new Integer(
+ XPathUtils.getAttributeValue(samlAssertion, MINOR_VERSION_XPATH, "-1")).intValue());
+ authData.setAssertionID(
+ XPathUtils.getAttributeValue(samlAssertion, ASSERTION_ID_XPATH, ""));
+ authData.setIssuer(
+ XPathUtils.getAttributeValue(samlAssertion, ISSUER_XPATH, ""));
+ authData.setIssueInstant(
+ XPathUtils.getAttributeValue(samlAssertion, ISSUE_INSTANT_XPATH, ""));
+ authData.setVPK(
+ XPathUtils.getElementValue(samlAssertion, VPK_XPATH, ""));
+ authData.setIdentificationValue(
+ XPathUtils.getElementValue(samlAssertion, ZMRZAHL_XPATH, ""));
+ authData.setGivenName(
+ XPathUtils.getElementValue(samlAssertion, GIVEN_NAME_XPATH, ""));
+ authData.setFamilyName(
+ XPathUtils.getElementValue(samlAssertion, FAMILY_NAME_XPATH, ""));
+ authData.setDateOfBirth(
+ XPathUtils.getElementValue(samlAssertion, DATE_OF_BIRTH_XPATH, ""));
+ authData.setQualifiedCertificate(BoolUtils.valueOf(
+ XPathUtils.getElementValue(samlAssertion, IS_QUALIFIED_CERT_XPATH, "")));
+ String publicAuthority =
+ XPathUtils.getElementValue(samlAssertion, PUBLIC_AUTHORITY_XPATH, null);
+ if (publicAuthority == null) {
+ authData.setPublicAuthority(false);
+ authData.setPublicAuthorityCode("");
+ }
+ else {
+ authData.setPublicAuthority(true);
+ if (! publicAuthority.equalsIgnoreCase("true"))
+ authData.setPublicAuthorityCode(publicAuthority);
+ }
+ return authData;
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString() }, t);
+ }
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/parser/SAMLResponseParser.java b/id.server/src/at/gv/egovernment/moa/id/proxy/parser/SAMLResponseParser.java
new file mode 100644
index 000000000..9f77578fd
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/parser/SAMLResponseParser.java
@@ -0,0 +1,100 @@
+package at.gv.egovernment.moa.id.proxy.parser;
+
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.ParseException;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+import at.gv.egovernment.moa.id.data.SAMLStatus;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * Parser for the <code>&lt;samlp:Response&gt;</code> returned by the
+ * <code>GetAuthenticationData</code> web service.
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class SAMLResponseParser implements Constants {
+ /** Element containing the samlResponse */
+ private Element samlResponse;
+ /** Xpath prefix for reaching SAMLP Namespaces */
+ private static String SAMLP = SAMLP_PREFIX + ":";
+ /** Xpath prefix for reaching SAML Namespaces */
+ private static String SAML = SAML_PREFIX + ":";
+ /** Xpath prefix for reaching PersonData Namespaces */
+ private static String PR = PD_PREFIX + ":";
+ /** Xpath expression for reaching the SAMLP:Response element */
+ private static final String ROOT =
+ "/" + SAMLP + "Response/";
+ /** Xpath expression for reaching the SAMLP:Status element */
+ private static final String STATUS_XPATH =
+ ROOT +
+ SAMLP + "Status/";
+ /** Xpath expression for reaching the SAMLP:StatusCode_Value attribute */
+ private static final String STATUSCODE_XPATH =
+ STATUS_XPATH +
+ SAMLP + "StatusCode/@Value";
+ /** Xpath expression for reaching the SAMLP:SubStatusCode_Value attribute */
+ private static final String SUBSTATUSCODE_XPATH =
+ STATUS_XPATH +
+ SAMLP + "StatusCode/" +
+ SAMLP + "StatusCode/@Value";
+ /** Xpath expression for reaching the SAMLP:StatusMessage element */
+ private static final String STATUSMESSAGE_XPATH =
+ STATUS_XPATH +
+ SAMLP + "StatusMessage";
+ /** Xpath expression for reaching the SAML:Assertion element */
+ private static String ASSERTION_XPATH =
+ ROOT +
+ SAML + "Assertion";
+
+ /**
+ * Constructor
+ * @param samlResponse the <code>&lt;samlp:Response&gt;</code> as a DOM element
+ */
+ public SAMLResponseParser(Element samlResponse) {
+ this.samlResponse = samlResponse;
+ }
+
+ /**
+ * Parses the <code>&lt;samlp:StatusCode&gt;</code> from the <code>&lt;samlp:Response&gt;</code>.
+ * @return <code>AuthenticationData</code> object
+ * @throws ParseException on any parsing error
+ */
+ public SAMLStatus parseStatusCode()
+ throws ParseException {
+
+ SAMLStatus status = new SAMLStatus();
+ try {
+ status.setStatusCode(
+ XPathUtils.getAttributeValue(samlResponse, STATUSCODE_XPATH, ""));
+ status.setSubStatusCode(
+ XPathUtils.getAttributeValue(samlResponse, SUBSTATUSCODE_XPATH, ""));
+ status.setStatusMessage(
+ XPathUtils.getElementValue(samlResponse, STATUSMESSAGE_XPATH, ""));
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString() }, t);
+ }
+ return status;
+ }
+
+ /**
+ * Parses the <code>&lt;saml:Assertion&gt;</code> from the <code>&lt;samlp:Response&gt;</code>.
+ * @return <code>AuthenticationData</code> object
+ * @throws ParseException on any parsing error
+ */
+ public AuthenticationData parseAuthenticationData()
+ throws ParseException {
+
+ Element samlAssertion;
+ try {
+ samlAssertion = (Element)XPathUtils.selectSingleNode(samlResponse, ASSERTION_XPATH);
+ }
+ catch (Throwable t) {
+ throw new ParseException("parser.01", new Object[] { t.toString() }, t);
+ }
+ return new AuthenticationDataAssertionParser(samlAssertion).parseAuthenticationData();
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ConfigurationServlet.java b/id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ConfigurationServlet.java
new file mode 100644
index 000000000..a00c48387
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ConfigurationServlet.java
@@ -0,0 +1,73 @@
+package at.gv.egovernment.moa.id.proxy.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egovernment.moa.id.proxy.MOAIDProxyInitializer;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Servlet requested for updating the MOA-ID Auth configuration from configuration file
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ConfigurationServlet extends HttpServlet {
+ /** The standard String for DTD Doc-type */
+ private static final String DOC_TYPE =
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n";
+
+ /**
+ * Handle a HTTP GET request, used to indicated that the MOA
+ * configuration needs to be updated (reloaded).
+ *
+ * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
+ */
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ MOAIDMessageProvider msg = MOAIDMessageProvider.getInstance();
+ PrintWriter out;
+
+ response.setContentType("text/html");
+ out = response.getWriter();
+ out.println(DOC_TYPE);
+ out.println("<head><title>MOA configuration update</title></head>");
+ out.println("<body bgcolor=\"#FFFFFF\">");
+ try {
+ MOAIDProxyInitializer.initialize();
+ String message = msg.getMessage("config.00", null);
+ Logger.info(message);
+ out.println("<p><b>");
+ out.println(message);
+ out.println("</b></p>");
+ } catch (Throwable t) {
+ String errorMessage = msg.getMessage("config.04", null);
+ Logger.error(errorMessage, t);
+ out.println("<p><b>");
+ out.println(errorMessage);
+ out.println("</b></p>");
+ }
+ out.println("</body>");
+
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Do the same as <code>doGet</code>.
+ *
+ * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest, HttpServletResponse)
+ */
+ public void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ doGet(request, response);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ProxyException.java b/id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ProxyException.java
new file mode 100644
index 000000000..0080c010e
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ProxyException.java
@@ -0,0 +1,35 @@
+package at.gv.egovernment.moa.id.proxy.servlet;
+
+import at.gv.egovernment.moa.id.MOAIDException;
+
+/**
+ * Exception thrown while proxying a request to the online application
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ProxyException extends MOAIDException {
+
+ /**
+ * Constructor for ProxyException.
+ * @param messageId
+ * @param parameters
+ */
+ public ProxyException(String messageId, Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+ /**
+ * Constructor for ProxyException.
+ * @param messageId
+ * @param parameters
+ * @param wrapped
+ */
+ public ProxyException(
+ String messageId,
+ Object[] parameters,
+ Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ProxyServlet.java b/id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ProxyServlet.java
new file mode 100644
index 000000000..c52de2ba8
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/proxy/servlet/ProxyServlet.java
@@ -0,0 +1,531 @@
+package at.gv.egovernment.moa.id.proxy.servlet;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.HttpURLConnection;
+import java.net.URLEncoder;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.net.ssl.SSLSocketFactory;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import at.gv.egovernment.moa.id.AuthenticationException;
+import at.gv.egovernment.moa.id.BuildException;
+import at.gv.egovernment.moa.id.MOAIDException;
+import at.gv.egovernment.moa.id.ParseException;
+import at.gv.egovernment.moa.id.ServiceException;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.config.proxy.ProxyConfigurationProvider;
+import at.gv.egovernment.moa.id.config.proxy.OAConfiguration;
+import at.gv.egovernment.moa.id.config.proxy.OAProxyParameter;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+import at.gv.egovernment.moa.id.data.CookieManager;
+import at.gv.egovernment.moa.id.proxy.ConnectionBuilder;
+import at.gv.egovernment.moa.id.proxy.ConnectionBuilderFactory;
+import at.gv.egovernment.moa.id.proxy.LoginParameterResolver;
+import at.gv.egovernment.moa.id.proxy.LoginParameterResolverFactory;
+import at.gv.egovernment.moa.id.proxy.MOAIDProxyInitializer;
+import at.gv.egovernment.moa.id.proxy.invoke.GetAuthenticationDataInvoker;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.id.util.SSLUtils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.Base64Utils;
+
+/**
+ * Servlet requested for logging in at an online application,
+ * and then for proxying requests to the online application.
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class ProxyServlet extends HttpServlet {
+ /** Name of the Parameter for the Target */
+ private static final String PARAM_TARGET = "Target";
+ /** Name of the Parameter for the SAMLArtifact */
+ private static final String PARAM_SAMLARTIFACT = "SAMLArtifact";
+
+ /** Name of the Attribute for the PublicURLPrefix */
+ private static final String ATT_PUBLIC_URLPREFIX = "PublicURLPrefix";
+ /** Name of the Attribute for the RealURLPrefix */
+ private static final String ATT_REAL_URLPREFIX = "RealURLPrefix";
+ /** Name of the Attribute for the SSLSocketFactory */
+ private static final String ATT_SSL_SOCKET_FACTORY = "SSLSocketFactory";
+ /** Name of the Attribute for the LoginHeaders */
+ private static final String ATT_LOGIN_HEADERS = "LoginHeaders";
+ /** Name of the Attribute for the LoginParameters */
+ private static final String ATT_LOGIN_PARAMETERS = "LoginParameters";
+
+ /**
+ * @see javax.servlet.http.HttpServlet#service(HttpServletRequest, HttpServletResponse)
+ */
+ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+
+ Logger.debug("getRequestURL:" + req.getRequestURL().toString());
+ try {
+ if (req.getParameter(PARAM_SAMLARTIFACT) != null && req.getParameter(PARAM_TARGET) != null)
+ login(req, resp);
+ else
+ tunnelRequest(req, resp);
+ }
+ catch (MOAIDException ex) {
+ handleError(resp, ex.toString(), ex);
+ }
+ catch (Throwable ex) {
+ handleError(resp, ex.toString(), ex);
+ }
+ }
+
+ /**
+ * Login to online application at first call of servlet for a user session.<br/>
+ * <ul>
+ * <li>Acquires authentication data from the MOA-ID Auth component.</li>
+ * <li>Reads configuration data for the online application.</li>
+ * <li>Resolves login parameters.</li>
+ * <li>Sets up an SSLSocketFactory in case of a secure connection to the online application.</li>
+ * <li>For a stateless online application, stores data in the HttpSession.</li>
+ * <li>Tunnels the request to the online application.</li>
+ * </ul>
+ * @param req
+ * @param resp
+ * @throws ConfigurationException when wrong configuration is encountered
+ * @throws ProxyException when wrong configuration is encountered
+ * @throws BuildException while building the request for MOA-ID Auth
+ * @throws ServiceException while invoking MOA-ID Auth
+ * @throws ParseException while parsing the response from MOA-ID Auth
+ */
+ private void login(HttpServletRequest req, HttpServletResponse resp) throws ConfigurationException, ProxyException, BuildException, ServiceException, ParseException, AuthenticationException {
+
+ String samlArtifact = req.getParameter(PARAM_SAMLARTIFACT);
+ Logger.debug("moa-id-proxy login " + PARAM_SAMLARTIFACT + ": " + samlArtifact);
+ // String target = req.getParameter(PARAM_TARGET); parameter given but not processed
+
+ // get authentication data from the MOA-ID Auth component
+ AuthenticationData authData = new GetAuthenticationDataInvoker().getAuthenticationData(samlArtifact);
+
+ String urlRequested = req.getRequestURL().toString();
+
+ // read configuration data
+ ProxyConfigurationProvider proxyConf = ProxyConfigurationProvider.getInstance();
+ OAProxyParameter oaParam = proxyConf.getOnlineApplicationParameter(urlRequested);
+ if (oaParam == null) {
+ throw new ProxyException("proxy.02", new Object[] { urlRequested });
+ }
+ String publicURLPrefix = oaParam.getPublicURLPrefix();
+ Logger.debug("OA: " + publicURLPrefix);
+ OAConfiguration oaConf = oaParam.getOaConfiguration();
+ ConnectionParameter oaConnParam = oaParam.getConnectionParameter();
+ String realURLPrefix = oaConnParam.getUrl();
+
+ // resolve login parameters to be forwarded to online application
+ LoginParameterResolver lpr = LoginParameterResolverFactory.getLoginParameterResolver(publicURLPrefix);
+ String clientIPAddress = req.getRemoteAddr();
+ Map loginHeaders = null;
+ Map loginParameters = null;
+ if (oaConf.getAuthType().equals(OAConfiguration.PARAM_AUTH))
+ loginParameters = lpr.getAuthenticationParameters(oaConf, authData, clientIPAddress);
+ else
+ loginHeaders = lpr.getAuthenticationHeaders(oaConf, authData, clientIPAddress);
+
+ // setup SSLSocketFactory for communication with the online application
+ SSLSocketFactory ssf = null;
+ if (oaConnParam.isHTTPSURL()) {
+ try {
+ ssf = SSLUtils.getSSLSocketFactory(proxyConf, oaConnParam);
+ }
+ catch (Throwable ex) {
+ throw new ProxyException("proxy.05", new Object[] { oaConnParam.getUrl(), ex.toString()}, ex);
+ }
+ }
+
+ try {
+ // for stateless online application, store data in HttpSession
+ String loginType = oaConf.getLoginType();
+ Logger.debug("Login type: " + loginType);
+ if (loginType.equals(OAConfiguration.LOGINTYPE_STATELESS)) {
+ HttpSession session = req.getSession();
+ int sessionTimeOut = oaParam.getSessionTimeOut();
+ if (sessionTimeOut == 0)
+ sessionTimeOut = 60 * 60; // default 1 h
+ session.setMaxInactiveInterval(sessionTimeOut);
+ session.setAttribute(ATT_PUBLIC_URLPREFIX, publicURLPrefix);
+ session.setAttribute(ATT_REAL_URLPREFIX, realURLPrefix);
+ session.setAttribute(ATT_SSL_SOCKET_FACTORY, ssf);
+ session.setAttribute(ATT_LOGIN_HEADERS, loginHeaders);
+ session.setAttribute(ATT_LOGIN_PARAMETERS, loginParameters);
+ Logger.debug("moa-id-proxy: HTTPSession angelegt");
+ }
+
+ // tunnel request to the online application
+ int respcode = tunnelRequest(req, resp, loginHeaders, loginParameters, publicURLPrefix, realURLPrefix, ssf);
+ if (respcode == 401)
+ {
+ Logger.debug("Got 401, trying again");
+
+ respcode = tunnelRequest(req, resp, loginHeaders, loginParameters, publicURLPrefix, realURLPrefix, ssf);
+ if (respcode == 401)
+ throw new ProxyException("proxy.12", new Object[] { realURLPrefix});
+ }
+ }
+ catch (ProxyException ex) {
+ throw new ProxyException("proxy.12", new Object[] { realURLPrefix});
+ }
+ catch (Throwable ex) {
+ throw new ProxyException("proxy.04", new Object[] { urlRequested, ex.toString()}, ex);
+ }
+ }
+
+ /**
+ * Tunnels a request to the stateless online application using data stored in the HTTP session.
+ * @param req HTTP request
+ * @param resp HTTP response
+ * @throws IOException if an I/O error occurs
+ */
+ private void tunnelRequest(HttpServletRequest req, HttpServletResponse resp) throws ProxyException, IOException {
+
+ Logger.debug("Tunnel request (stateless)");
+ HttpSession session = req.getSession(false);
+ if (session == null)
+ throw new ProxyException("proxy.07", null);
+ String publicURLPrefix = (String) session.getAttribute(ATT_PUBLIC_URLPREFIX);
+ String realURLPrefix = (String) session.getAttribute(ATT_REAL_URLPREFIX);
+ SSLSocketFactory ssf = (SSLSocketFactory) session.getAttribute(ATT_SSL_SOCKET_FACTORY);
+ Map loginHeaders = (Map) session.getAttribute(ATT_LOGIN_HEADERS);
+ Map loginParameters = (Map) session.getAttribute(ATT_LOGIN_PARAMETERS);
+ if (publicURLPrefix == null || realURLPrefix == null)
+ throw new ProxyException("proxy.08", new Object[] { req.getRequestURL().toString()});
+
+ int respcode = tunnelRequest(req, resp, loginHeaders, loginParameters, publicURLPrefix, realURLPrefix, ssf);
+ if (respcode == 401)
+ {
+ Logger.debug("Got 401, trying again");
+ respcode = tunnelRequest(req, resp, loginHeaders, loginParameters, publicURLPrefix, realURLPrefix, ssf);
+ if (respcode == 401)
+ throw new ProxyException("proxy.12", new Object[] { realURLPrefix});
+ }
+ }
+
+/**
+ * Tunnels a request to the online application using given URL mapping and SSLSocketFactory.
+ * This method returns the ResponseCode of the request to the online application.
+ * @param req HTTP request
+ * @param resp HTTP response
+ * @param loginHeaders header field/values to be inserted for purposes of authentication;
+ * may be <code>null</code>
+ * @param loginParameters parameter name/values to be inserted for purposes of authentication;
+ * may be <code>null</code>
+ * @param publicURLPrefix prefix of request URL to be substituted for the <code>realURLPrefix</code>
+ * @param realURLPrefix prefix of online application URL to substitute the <code>publicURLPrefix</code>
+ * @param ssf SSLSocketFactory to use
+ * @throws IOException if an I/O error occurs
+ */
+private int tunnelRequest(HttpServletRequest req, HttpServletResponse resp, Map loginHeaders, Map loginParameters, String publicURLPrefix, String realURLPrefix, SSLSocketFactory ssf)
+ throws IOException {
+
+ // collect headers from request
+ Map headers = new HashMap();
+ for (Enumeration enum = req.getHeaderNames(); enum.hasMoreElements();) {
+ String headerKey = (String) enum.nextElement();
+ //We ignore any Basic-Auth-Headers from the client
+ if (headerKey.equalsIgnoreCase("Authorization"))
+ { Logger.debug("Ignoring authorization-header from browser: " +req.getHeader(headerKey) );
+ }
+ else
+ headers.put(headerKey, req.getHeader(headerKey));
+ }
+ // collect login headers, possibly overwriting headers from request
+ if (loginHeaders != null) {
+ for (Iterator iter = loginHeaders.keySet().iterator(); iter.hasNext();) {
+ String headerKey = (String) iter.next();
+ headers.put(headerKey, loginHeaders.get(headerKey));
+ }
+ }
+ // collect parameters from request
+ Map parameters = new HashMap();
+ for (Enumeration enum = req.getParameterNames(); enum.hasMoreElements();) {
+ String paramName = (String) enum.nextElement();
+ parameters.put(paramName, req.getParameter(paramName));
+ }
+ // collect login parameters, possibly overwriting parameters from request
+ if (loginParameters != null) {
+ for (Iterator iter = loginParameters.keySet().iterator(); iter.hasNext();) {
+ String paramName = (String) iter.next();
+ parameters.put(paramName, loginParameters.get(paramName));
+ }
+ }
+
+ headers.remove("content-length");
+ parameters.remove(PARAM_SAMLARTIFACT);
+ parameters.remove(PARAM_TARGET);
+
+ ConnectionBuilder cb = ConnectionBuilderFactory.getConnectionBuilder(publicURLPrefix);
+ HttpURLConnection conn = cb.buildConnection(req, publicURLPrefix, realURLPrefix, ssf, parameters);
+
+ //Set Cookies...
+
+ String cookieString = CookieManager.getInstance().getCookie(req.getSession().getId());
+ if (cookieString!=null)
+ {
+ //If we get Cookies from Client, we put them throgh if they dont exist/conflict with the stored Cookies
+ for (Iterator iter = headers.keySet().iterator(); iter.hasNext();) {
+ String headerKey = (String) iter.next();
+ String headerValue = (String) headers.get(headerKey);
+ if (headerKey.equalsIgnoreCase("Cookie"))
+ CookieManager.getInstance().saveOldCookies(req.getSession().getId(), headerValue);
+ }
+ cookieString = CookieManager.getInstance().getCookie(req.getSession().getId());
+ headers.put("cookie", cookieString);
+ }
+
+ // set headers as request properties of URLConnection
+ for (Iterator iter = headers.keySet().iterator(); iter.hasNext();) {
+ String headerKey = (String) iter.next();
+ String headerValue = (String) headers.get(headerKey);
+ conn.setRequestProperty(headerKey, headerValue);
+ Logger.debug("Req header " + headerKey + ": " + headers.get(headerKey));
+ if (Logger.isDebugEnabled() && isBasicAuthenticationHeader(headerKey, headerValue)) {
+ String credentials = headerValue.substring(6);
+ String userIDPassword = new String(Base64Utils.decode(credentials, false));
+ Logger.debug(":UserID:Password: :" + userIDPassword + ":");
+ }
+ }
+ // Write out parameters into output stream of URLConnection.
+ // On GET request, do not send parameters in any case,
+ // otherwise HttpURLConnection would send a POST.
+ if (!"get".equalsIgnoreCase(req.getMethod()) && !parameters.isEmpty()) {
+ boolean firstParam = true;
+ StringWriter sb = new StringWriter();
+ for (Iterator iter = parameters.keySet().iterator(); iter.hasNext();) {
+ String paramname = (String) iter.next();
+ String value = URLEncoder.encode((String) parameters.get(paramname));
+ if (firstParam)
+ firstParam = false;
+ else
+ sb.write("&");
+ sb.write(paramname);
+ sb.write("=");
+ sb.write(value);
+ Logger.debug("Req param " + paramname + ": " + value);
+ }
+ PrintWriter reqOut = new PrintWriter(conn.getOutputStream());
+ reqOut.write(sb.toString());
+ reqOut.flush();
+ reqOut.close();
+ }
+ // connect
+ conn.connect();
+
+ // Read response status and content type.
+ // If the connection returns a 401 disconnect and return
+ // otherwise the attempt to read data from that connection
+ // will result in an error
+
+ if (conn.getResponseCode()==HttpURLConnection.HTTP_UNAUTHORIZED)
+ {
+ Logger.debug("Found 401... searching cookies");
+ String headerKey;
+
+ int i = 1;
+ CookieManager cm = CookieManager.getInstance();
+ while ((headerKey = conn.getHeaderFieldKey(i)) != null) {
+ String headerValue = conn.getHeaderField(i);
+ if (headerKey.equalsIgnoreCase("set-cookie"))
+ { cm.saveCookie(req.getSession().getId(), headerValue);
+ cm.add401(req.getSession().getId(),headerValue);
+ Logger.debug("Cookie " + headerValue);
+ Logger.debug("CookieSession " + req.getSession().getId());
+ }
+ i++;
+ }
+
+ conn.disconnect();
+ return conn.getResponseCode();
+ }
+ resp.setStatus(conn.getResponseCode());
+ resp.setContentType(conn.getContentType());
+
+ // Read response headers
+ // Omit response header "content-length" if response header "Transfer-encoding: chunked" is set.
+ // Otherwise, the connection will not be kept alive, resulting in subsequent missing requests.
+ // See JavaDoc of javax.servlet.http.HttpServlet:
+ // When using HTTP 1.1 chunked encoding (which means that the response has a Transfer-Encoding header), do not set the Content-Length header.
+ Map respHeaders = new HashMap();
+ boolean chunked = false;
+ String contentLengthKey = null;
+ String transferEncodingKey = null;
+ int i = 1;
+ String headerKey;
+ while ((headerKey = conn.getHeaderFieldKey(i)) != null) {
+ String headerValue = conn.getHeaderField(i);
+ respHeaders.put(headerKey, headerValue);
+ if (isTransferEncodingChunkedHeader(headerKey, headerValue)) {
+ chunked = true;
+ transferEncodingKey = headerKey;
+ }
+ CookieManager cm = CookieManager.getInstance();
+ if (headerKey.equalsIgnoreCase("set-cookie"))
+ { cm.saveCookie(req.getSession().getId(), headerValue);
+ Logger.debug("Cookie " + headerValue);
+ Logger.debug("CookieSession " + req.getSession().getId());
+ }
+ if ("content-length".equalsIgnoreCase(headerKey))
+ contentLengthKey = headerKey;
+ Logger.debug("Resp header " + headerKey + ": " + headerValue);
+ i++;
+ }
+ if (chunked && contentLengthKey != null) {
+ respHeaders.remove(transferEncodingKey);
+ Logger.debug("Resp header " + transferEncodingKey + " REMOVED");
+ }
+
+ //Get a Hash-Map of all 401-set-cookies
+ HashMap cookies401 = CookieManager.getInstance().get401(req.getSession().getId());
+
+ for (Iterator iter = respHeaders.keySet().iterator(); iter.hasNext();) {
+ headerKey = (String) iter.next();
+
+ if (headerKey.equalsIgnoreCase("Set-Cookie"))
+ {
+ String headerValue = (String) respHeaders.get(headerKey);
+ Logger.debug("Found 'Set-Cookie' in ResponseHeaders: " + headerValue);
+ if(!cookies401.containsKey(headerValue.substring(0, headerValue.indexOf("="))))
+ {
+ // If we dont already have a Set-Cookie-Value for THAT Cookie we create one...
+ CookieManager.getInstance().add401(req.getSession().getId(), headerValue);
+ }
+ }
+ }
+
+ //write out all Responseheaders != "set-cookie"
+ for (Iterator iter = respHeaders.keySet().iterator(); iter.hasNext();) {
+ headerKey = (String) iter.next();
+ if (!headerKey.equalsIgnoreCase("Set-Cookie"))
+ resp.addHeader(headerKey, (String) respHeaders.get(headerKey));
+ }
+
+ //write out all Responseheaders = "set-cookie"
+ cookies401 = CookieManager.getInstance().get401(req.getSession().getId());
+ Iterator cookie_i = cookies401.values().iterator();
+ while (cookie_i.hasNext()) {
+ String element = (String) cookie_i.next();
+ resp.addHeader("Set-Cookie", element);
+ }
+ //Delete all "Set-Cookie" - Values
+ CookieManager.getInstance().clear401(req.getSession().getId());
+
+ // read response stream
+ Logger.debug("Resp from " + conn.getURL().toString() + ": status " + conn.getResponseCode());
+ // Load content unless the server lets us know that the content is NOT MODIFIED...
+ if (conn.getResponseCode()!=HttpURLConnection.HTTP_NOT_MODIFIED)
+ {
+ BufferedInputStream respIn = new BufferedInputStream(conn.getInputStream());
+ Logger.debug("Got Inputstream");
+ BufferedOutputStream respOut = new BufferedOutputStream(resp.getOutputStream());
+ Logger.debug("Got Outputstream");
+ int ch;
+ while ((ch = respIn.read()) >= 0)
+ respOut.write(ch);
+ respOut.close();
+ respIn.close();
+ }
+ else
+ Logger.debug("Found 304 NOT MODIFIED...");
+ conn.disconnect();
+ Logger.debug("Request done");
+
+
+ return conn.getResponseCode();
+}
+/**
+ * Determines whether a HTTP header is a basic authentication header of the kind "Authorization: Basic ..."
+ *
+ * @param headerKey header name
+ * @param headerValue header value
+ * @return true for a basic authentication header
+ */
+private boolean isBasicAuthenticationHeader(String headerKey, String headerValue) {
+ if (!"authorization".equalsIgnoreCase(headerKey))
+ return false;
+ if (headerValue.length() < "basic".length())
+ return false;
+ String authenticationSchema = headerValue.substring(0, "basic".length());
+ return "basic".equalsIgnoreCase(authenticationSchema);
+}
+/**
+ * Determines whether a HTTP header is "Transfer-encoding" header with value containing "chunked"
+ *
+ * @param headerKey header name
+ * @param headerValue header value
+ * @return true for a "Transfer-encoding: chunked" header
+ */
+private boolean isTransferEncodingChunkedHeader(String headerKey, String headerValue) {
+ if (!"transfer-encoding".equalsIgnoreCase(headerKey))
+ return false;
+ return headerValue.indexOf("chunked") >= 0 || headerValue.indexOf("Chunked") >= 0 || headerValue.indexOf("CHUNKED") >= 0;
+}
+
+/**
+ * Calls the web application initializer.
+ *
+ * @see javax.servlet.Servlet#init(ServletConfig)
+ */
+public void init(ServletConfig servletConfig) throws ServletException {
+ try {
+ MOAIDProxyInitializer.initialize();
+ Logger.info(MOAIDMessageProvider.getInstance().getMessage("proxy.00", null));
+ }
+ catch (Exception ex) {
+ Logger.fatal(MOAIDMessageProvider.getInstance().getMessage("proxy.06", null), ex);
+ throw new ServletException(ex);
+ }
+}
+/**
+ * Handles an error in proxying the request.
+ * <ul>
+ * <li>Logs the error.</li>
+ * <li>Outputs an HTML error page.</li>
+ * </ul>
+ * @param resp the HttpServletResponse
+ * @param errorMessage error message to be used
+ * @param ex the exception to be logged
+ */
+private void handleError(HttpServletResponse resp, String errorMessage, Throwable ex) {
+ Logger.error(errorMessage, ex);
+ String htmlCode =
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">"
+ + "<html><head><title>"
+ + MOAIDMessageProvider.getInstance().getMessage("proxy.10", null)
+ + "</title></head><body>"
+ + "<h1>"
+ + MOAIDMessageProvider.getInstance().getMessage("proxy.10", null)
+ + "</h1>"
+ + "<p>"
+ + MOAIDMessageProvider.getInstance().getMessage("proxy.11", null)
+ + "</p>"
+ + "<p>"
+ + errorMessage
+ + "</p>"
+ + "</body></html>";
+ resp.setContentType("text/html");
+ try {
+ OutputStream respOut = resp.getOutputStream();
+ respOut.write(htmlCode.getBytes());
+ respOut.flush();
+ }
+ catch (IOException ioex) {
+ Logger.error("", ioex);
+ }
+}
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/util/AxisSecureSocketFactory.java b/id.server/src/at/gv/egovernment/moa/id/util/AxisSecureSocketFactory.java
new file mode 100644
index 000000000..8967bdbba
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/util/AxisSecureSocketFactory.java
@@ -0,0 +1,213 @@
+package at.gv.egovernment.moa.id.util;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+import java.util.Hashtable;
+
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.apache.axis.components.net.BooleanHolder;
+import org.apache.axis.components.net.DefaultSocketFactory;
+import org.apache.axis.components.net.SecureSocketFactory;
+import org.apache.axis.components.net.TransportClientProperties;
+import org.apache.axis.components.net.TransportClientPropertiesFactory;
+import org.apache.axis.utils.Messages;
+import org.apache.axis.utils.XMLUtils;
+
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Secure socket factory for Axis webs service clients of the MOA-ID component,
+ * which are the MOA-SP calls from MOA-ID Auth,
+ * and the MOA-ID Auth calls from MOA-ID Proxy.
+ * <br/>Use this initialization code:<br/>
+ * <code> // ConnectionParameter connParam = ... get from ConfigurationProvider
+ * AxisSecureSocketFactory.initialize(connParam);</code>
+ * <br/>See the Apache Axis documentation on how to configure this class
+ * as the default secure socket factory to be used by Axis.
+ * <br/>
+ * This code has been copied from <code>JSSESocketFactory</code>, the
+ * method <code>initialize()</code> has been added.
+ *
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class AxisSecureSocketFactory
+ extends DefaultSocketFactory implements SecureSocketFactory {
+
+ /** Field sslFactory */
+ private static SSLSocketFactory sslFactory;
+
+ /**
+ * Constructor for AxisSecureSocketFactory.
+ * @param attributes ???
+ */
+ public AxisSecureSocketFactory(Hashtable attributes) {
+ super(attributes);
+ }
+ /**
+ * Initializes the factory by setting the connection parameters to be used for
+ * setting the secure socket factory, and by setting the system property
+ * <code>axis.socketSecureFactory</code>.
+ * @param connParam <code>ConnectionParameter</code> to derive the
+ * secure socket factory from
+ */
+ public static void initialize(SSLSocketFactory ssf)
+ throws IOException, GeneralSecurityException {
+
+ Logger.debug("Initialize AxisSecureSocketFactory");
+ sslFactory = ssf;
+ }
+
+ /**
+ * creates a secure socket
+ *
+ * @param host
+ * @param port
+ * @param otherHeaders
+ * @param useFullURL
+ *
+ * @return Socket
+ * @throws Exception
+ */
+ public Socket create(
+ String host,
+ int port,
+ StringBuffer otherHeaders,
+ BooleanHolder useFullURL)
+ throws Exception {
+ if (port == -1) {
+ port = 443;
+ }
+
+ TransportClientProperties tcp =
+ TransportClientPropertiesFactory.create("https");
+
+ boolean hostInNonProxyList =
+ isHostInNonProxyList(host, tcp.getNonProxyHosts());
+
+ Socket sslSocket = null;
+ if (tcp.getProxyHost().length() == 0 || hostInNonProxyList) {
+ // direct SSL connection
+ sslSocket = sslFactory.createSocket(host, port);
+ }
+ else {
+
+ // Default proxy port is 80, even for https
+ int tunnelPort =
+ (tcp.getProxyPort().length() != 0)
+ ? Integer.parseInt(tcp.getProxyPort())
+ : 80;
+ if (tunnelPort < 0)
+ tunnelPort = 80;
+
+ // Create the regular socket connection to the proxy
+ Socket tunnel = new Socket(tcp.getProxyHost(), tunnelPort);
+
+ // The tunnel handshake method (condensed and made reflexive)
+ OutputStream tunnelOutputStream = tunnel.getOutputStream();
+ PrintWriter out =
+ new PrintWriter(
+ new BufferedWriter(new OutputStreamWriter(tunnelOutputStream)));
+
+ // More secure version... engage later?
+ // PasswordAuthentication pa =
+ // Authenticator.requestPasswordAuthentication(
+ // InetAddress.getByName(tunnelHost),
+ // tunnelPort, "SOCK", "Proxy","HTTP");
+ // if(pa == null){
+ // printDebug("No Authenticator set.");
+ // }else{
+ // printDebug("Using Authenticator.");
+ // tunnelUser = pa.getUserName();
+ // tunnelPassword = new String(pa.getPassword());
+ // }
+ out.print(
+ "CONNECT "
+ + host
+ + ":"
+ + port
+ + " HTTP/1.0\r\n"
+ + "User-Agent: AxisClient");
+ if (tcp.getProxyUser().length() != 0
+ && tcp.getProxyPassword().length() != 0) {
+
+ // add basic authentication header for the proxy
+ String encodedPassword =
+ XMLUtils.base64encode(
+ (tcp.getProxyUser() + ":" + tcp.getProxyPassword()).getBytes());
+
+ out.print("\nProxy-Authorization: Basic " + encodedPassword);
+ }
+ out.print("\nContent-Length: 0");
+ out.print("\nPragma: no-cache");
+ out.print("\r\n\r\n");
+ out.flush();
+ InputStream tunnelInputStream = tunnel.getInputStream();
+
+ if (log.isDebugEnabled()) {
+ log.debug(
+ Messages.getMessage(
+ "isNull00",
+ "tunnelInputStream",
+ "" + (tunnelInputStream == null)));
+ }
+ String replyStr = "";
+
+ // Make sure to read all the response from the proxy to prevent SSL negotiation failure
+ // Response message terminated by two sequential newlines
+ int newlinesSeen = 0;
+ boolean headerDone = false; /* Done on first newline */
+
+ while (newlinesSeen < 2) {
+ int i = tunnelInputStream.read();
+
+ if (i < 0) {
+ throw new IOException("Unexpected EOF from proxy");
+ }
+ if (i == '\n') {
+ headerDone = true;
+ ++newlinesSeen;
+ }
+ else if (i != '\r') {
+ newlinesSeen = 0;
+ if (!headerDone) {
+ replyStr += String.valueOf((char) i);
+ }
+ }
+ }
+ if (!replyStr.startsWith("HTTP/1.0 200")
+ && !replyStr.startsWith("HTTP/1.1 200")) {
+ throw new IOException(
+ Messages.getMessage(
+ "cantTunnel00",
+ new String[] { tcp.getProxyHost(), "" + tunnelPort, replyStr }));
+ }
+
+ // End of condensed reflective tunnel handshake method
+ sslSocket = sslFactory.createSocket(tunnel, host, port, true);
+ if (log.isDebugEnabled()) {
+ log.debug(
+ Messages.getMessage(
+ "setupTunnel00",
+ tcp.getProxyHost(),
+ "" + tunnelPort));
+ }
+ }
+
+ ((SSLSocket) sslSocket).startHandshake();
+ if (log.isDebugEnabled()) {
+ log.debug(Messages.getMessage("createdSSL00"));
+ }
+ return sslSocket;
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/util/MOAIDMessageProvider.java b/id.server/src/at/gv/egovernment/moa/id/util/MOAIDMessageProvider.java
new file mode 100644
index 000000000..d31aa6ec1
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/util/MOAIDMessageProvider.java
@@ -0,0 +1,58 @@
+package at.gv.egovernment.moa.id.util;
+
+import java.util.Locale;
+
+import at.gv.egovernment.moa.util.Messages;
+
+/**
+ * A singleton wrapper around a <code>Message</code> object, providing the messages used in MOA-ID.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class MOAIDMessageProvider {
+
+ /** DEFAULT_MESSAGE_RESOURCES are resources/properties/id_messages */
+ private static final String[] DEFAULT_MESSAGE_RESOURCES =
+ { "resources/properties/id_messages" };
+ /** DEFAULT_MESSAGE_LOCALES are "de", "AT" */
+ private static final Locale[] DEFAULT_MESSAGE_LOCALES =
+ new Locale[] { new Locale("de", "AT") };
+ /** The instance for our singleton */
+ private static MOAIDMessageProvider instance;
+ /** The Messages */
+ private Messages messages;
+
+ /**
+ * Returns the single instance of <code>MOAIDMessageProvider</code>.
+ *
+ * @return the single instance of <code>MOAIDMessageProvider</code>
+ */
+ public static MOAIDMessageProvider getInstance() {
+ if (instance == null)
+ instance = new MOAIDMessageProvider(DEFAULT_MESSAGE_RESOURCES, DEFAULT_MESSAGE_LOCALES);
+ return instance;
+ }
+
+ /**
+ * Create a <code>MOAIDMessageProvider</code>.
+ *
+ * @param resourceNames The names of the resources containing the messages.
+ * @param locales The corresponding locales.
+ */
+ protected MOAIDMessageProvider(String[] resourceNames, Locale[] locales) {
+ this.messages = new Messages(resourceNames, locales);
+ }
+
+ /**
+ * Get the message corresponding to a given message ID.
+ *
+ * @param messageId The ID of the message.
+ * @param parameters The parameters to fill in into the message arguments.
+ * @return The formatted message.
+ */
+ public String getMessage(String messageId, Object[] parameters) {
+ return messages.getMessage(messageId, parameters);
+ }
+
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/util/Random.java b/id.server/src/at/gv/egovernment/moa/id/util/Random.java
new file mode 100644
index 000000000..da75b4213
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/util/Random.java
@@ -0,0 +1,22 @@
+package at.gv.egovernment.moa.id.util;
+
+import java.util.Date;
+
+/**
+ * Random number generator used to generate ID's
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class Random {
+
+ /** random number generator used */
+ private static java.util.Random random = new java.util.Random(new Date().getTime());
+ /**
+ * Creates a new random number, to be used as an ID.
+ *
+ * @return random long as a String
+ */
+ public static String nextRandom() {
+ return "" + random.nextLong();
+ }
+}
diff --git a/id.server/src/at/gv/egovernment/moa/id/util/SSLUtils.java b/id.server/src/at/gv/egovernment/moa/id/util/SSLUtils.java
new file mode 100644
index 000000000..f21b0880e
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/util/SSLUtils.java
@@ -0,0 +1,156 @@
+package at.gv.egovernment.moa.id.util;
+
+import iaik.pki.PKIConfiguration;
+import iaik.pki.PKIException;
+import iaik.pki.PKIFactory;
+import iaik.pki.PKIProfile;
+import iaik.pki.jsse.IAIKX509TrustManager;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.Security;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.net.ssl.SSLSocketFactory;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.ConfigurationProvider;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.iaik.config.PKIConfigurationImpl;
+import at.gv.egovernment.moa.id.iaik.pki.PKIProfileImpl;
+import at.gv.egovernment.moa.id.iaik.pki.jsse.MOAIDTrustManager;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.StreamUtils;
+
+import com.sun.net.ssl.HttpsURLConnection;
+import com.sun.net.ssl.KeyManager;
+import com.sun.net.ssl.SSLContext;
+import com.sun.net.ssl.TrustManager;
+
+/**
+ * Utility for a obtaining a secure socket factory using <code>IAIKX509TrustManager</code>.
+ * This <code>TrustManager</code> implementation features CRL checking.<br/>
+ * <code>SSLUtils</code> caches secure socket factories for given <code>ConnectionParameter</code>s.
+ *
+ * @author Paul Ivancsics
+ * @version $Id$
+ */
+public class SSLUtils {
+
+ /** SSLSocketFactory store, mapping URL->SSLSocketFactory **/
+ private static Map sslSocketFactories = new HashMap();
+
+ /**
+ * Initializes the SSLSocketFactory store.
+ */
+ public static void initialize() {
+ sslSocketFactories = new HashMap();
+ Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
+ System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
+ }
+
+ /**
+ * Creates an <code>SSLSocketFactory</code> which utilizes an
+ * <code>IAIKX509TrustManager</code> for the given trust store,
+ * and the given key store.
+ *
+ * @param conf configuration provider providing a generic properties pointing
+ * to trusted CA store and certificate store root
+ * @param connParam connection parameter containing the client key store settings
+ * to be used in case of client authentication;
+ * if <code>connParam.getClientKeyStore() == null</code>, client authentication
+ * is assumed to be disabled
+ * @return <code>SSLSocketFactory</code> to be used by an <code>HttpsURLConnection</code>
+ * @throws IOException thrown while reading key store file
+ * @throws GeneralSecurityException thrown while creating the socket factory
+ * @throws ConfigurationException on invalid configuration data
+ * @throws PKIException while initializing the <code>IAIKX509TrustManager</code>
+ */
+ public static SSLSocketFactory getSSLSocketFactory(
+ ConfigurationProvider conf,
+ ConnectionParameter connParam)
+ throws IOException, GeneralSecurityException, ConfigurationException, PKIException {
+
+ Logger.debug("Get SSLSocketFactory for " + connParam.getUrl());
+ // retrieve SSLSocketFactory if already created
+ SSLSocketFactory ssf = (SSLSocketFactory)sslSocketFactories.get(connParam.getUrl());
+ if (ssf != null)
+ return ssf;
+ // else create new SSLSocketFactory
+ String trustStoreURL = conf.getTrustedCACertificates();
+ if (trustStoreURL == null)
+ throw new ConfigurationException(
+ "config.08", new Object[] {"TrustedCACertificates"});
+ String acceptedServerCertURL = connParam.getAcceptedServerCertificates();
+ TrustManager[] tms = getTrustManagers(conf, trustStoreURL, acceptedServerCertURL);
+ KeyManager[] kms = at.gv.egovernment.moa.util.SSLUtils.getKeyManagers(
+ "pkcs12", connParam.getClientKeyStore(), connParam.getClientKeyStorePassword());
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(kms, tms, null);
+ ssf = ctx.getSocketFactory();
+ // store SSLSocketFactory
+ sslSocketFactories.put(connParam.getUrl(), ssf);
+ return ssf;
+ }
+
+ /**
+ * Initializes an <code>IAIKX509TrustManager</code> for a given trust store,
+ * using configuration data.
+ *
+ * @param conf MOA-ID configuration provider
+ * @param trustStoreURL trust store URL
+ * @param acceptedServerCertURL file URL pointing to directory containing accepted server SSL certificates
+ * @return <code>TrustManager</code> array containing the <code>IAIKX509TrustManager</code>
+ * @throws ConfigurationException on invalid configuration data
+ * @throws IOException on data-reading problems
+ * @throws PKIException while initializing the <code>IAIKX509TrustManager</code>
+ */
+ public static TrustManager[] getTrustManagers(
+ ConfigurationProvider conf, String trustStoreURL, String acceptedServerCertURL)
+ throws ConfigurationException, PKIException, IOException, GeneralSecurityException {
+
+ PKIConfiguration cfg = null;
+ if (! PKIFactory.getInstance().isAlreadyConfigured())
+ cfg = new PKIConfigurationImpl(conf);
+ PKIProfile profile = new PKIProfileImpl(trustStoreURL);
+ // This call fixes a bug occuring when PKIConfiguration is
+ // initialized by the MOA-SP initialization code, in case
+ // MOA-SP is called by API
+ MOAIDTrustManager.initializeLoggingContext();
+ IAIKX509TrustManager tm = new MOAIDTrustManager(acceptedServerCertURL);
+ tm.init(cfg, profile);
+ return new TrustManager[] {tm};
+ }
+ /**
+ * Reads a file, given by URL, into a byte array,
+ * securing the connection by IAIKX509TrustManager.
+ * @param connParam containing URL and accepted server certificates
+ * @param conf ConfigurationProvider for reading
+ * @return file content
+ * @throws ConfigurationException on invalid configuration data
+ * @throws PKIException on invalid configuration data
+ * @throws IOException on data-reading problems
+ * @throws GeneralSecurityException on security issues
+ */
+ public static byte[] readHttpsURL(ConfigurationProvider conf, ConnectionParameter connParam)
+ throws ConfigurationException, PKIException, IOException, GeneralSecurityException {
+
+ URL url = new URL(connParam.getUrl());
+ HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
+ conn.setRequestMethod("GET");
+ conn.setDoInput(true);
+ SSLSocketFactory sslSocketFactory = getSSLSocketFactory(conf, connParam);
+ conn.setSSLSocketFactory(sslSocketFactory);
+ conn.connect();
+ InputStream in = new BufferedInputStream(conn.getInputStream());
+ byte[] content = StreamUtils.readStream(in);
+ in.close();
+ conn.disconnect();
+ return content;
+ }
+
+}