aboutsummaryrefslogtreecommitdiff
path: root/id.server/src/at/gv/egovernment/moa/id/proxy
diff options
context:
space:
mode:
Diffstat (limited to 'id.server/src/at/gv/egovernment/moa/id/proxy')
-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
15 files changed, 1672 insertions, 0 deletions
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);
+ }
+}
+
+}