aboutsummaryrefslogtreecommitdiff
path: root/id.server/src/at/gv/egovernment/moa/id/auth
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/id/auth
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/id/auth')
-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
43 files changed, 5117 insertions, 0 deletions
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);
+ }
+
+}