# HG changeset patch # User Bjoern Ricks # Date 1342013516 0 # Node ID d7f76f197d8935073efcd55d46e7e062809702a2 # Parent f1030909eeb611950c11e77f0f98bbdc40b81d64 Refactor GGInA authentication Move authentication related classes to de.intevation.fly.client.server.auth package. Abstract the authentication classes to allow other authentications beside WAS/GGInA. flys-client/trunk@4936 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r f1030909eeb6 -r d7f76f197d89 flys-client/ChangeLog --- a/flys-client/ChangeLog Wed Jul 11 12:34:26 2012 +0000 +++ b/flys-client/ChangeLog Wed Jul 11 13:31:56 2012 +0000 @@ -1,3 +1,23 @@ +2012-07-11 Björn Ricks + + * src/main/java/de/intevation/flys/client/server/auth/Authentication.java, + src/main/java/de/intevation/flys/client/server/auth/AuthenticationFactory.java, + src/main/java/de/intevation/flys/client/server/auth/was/Namespaces.java, + src/main/java/de/intevation/flys/client/server/auth/was/ServiceException.java, + src/main/java/de/intevation/flys/client/server/auth/was/Signature.java, + src/main/java/de/intevation/flys/client/server/auth/was/Assertion.java, + src/main/java/de/intevation/flys/client/server/auth/was/Request.java, + src/main/java/de/intevation/flys/client/server/auth/was/Authenticator.java, + src/main/java/de/intevation/flys/client/server/auth/was/Response.java, + src/main/java/de/intevation/flys/client/server/auth/was/User.java, + src/main/java/de/intevation/flys/client/server/auth/Authenticator.java, + src/main/java/de/intevation/flys/client/server/auth/AuthenticationException.java, + src/main/java/de/intevation/flys/client/server/auth/User.java, + src/main/webapp/WEB-INF/web.xml: + Move authentication related classes to de.intevation.fly.client.server.auth + package. Abstract the authentication classes to allow other authentications + beside WAS/GGInA. + 2012-07-11 Björn Ricks * src/main/java/de/intevation/flys/client/server/GGInAFilter.java: Check filter config in web.xml for String false to deactivate the diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/GGInAFilter.java --- a/flys-client/src/main/java/de/intevation/flys/client/server/GGInAFilter.java Wed Jul 11 12:34:26 2012 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/GGInAFilter.java Wed Jul 11 13:31:56 2012 +0000 @@ -16,7 +16,7 @@ import org.apache.log4j.Logger; -import de.intevation.flys.client.server.was.User; +import de.intevation.flys.client.server.auth.was.User; /** ServletFilter used for GGInA authentification and certain authorisation. */ diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/LoginServlet.java --- a/flys-client/src/main/java/de/intevation/flys/client/server/LoginServlet.java Wed Jul 11 12:34:26 2012 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/LoginServlet.java Wed Jul 11 13:31:56 2012 +0000 @@ -1,7 +1,6 @@ package de.intevation.flys.client.server; import java.io.IOException; -import java.security.GeneralSecurityException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -9,23 +8,12 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.ssl.SSLSocketFactory; -import org.apache.http.impl.client.DefaultHttpClient; - import org.apache.log4j.Logger; -import de.intevation.flys.client.server.was.Assertion; -import de.intevation.flys.client.server.was.User; -import de.intevation.flys.client.server.was.Request; -import de.intevation.flys.client.server.was.Response; -import de.intevation.flys.client.server.was.ServiceException; -import de.intevation.flys.client.server.was.Signature; - - +import de.intevation.flys.client.server.auth.Authentication; +import de.intevation.flys.client.server.auth.AuthenticationException; +import de.intevation.flys.client.server.auth.AuthenticationFactory; +import de.intevation.flys.client.server.auth.User; public class LoginServlet extends HttpServlet { @@ -63,64 +51,28 @@ this.redirectFailure(resp); } try { - Response wasresp = this.auth(username, password, encoding); - if (wasresp == null || !wasresp.isSuccess()) { + Authentication aresp = this.auth(username, password, encoding); + if (aresp == null || !aresp.isSuccess()) { logger.debug("Athentication not successful"); this.redirectFailure(resp); } HttpSession session = req.getSession(); - User user = new User(username, password); + User user = aresp.getUser(); session.setAttribute("user", user); String uri = (String)session.getAttribute("requesturi"); this.redirectSuccess(resp, uri); - - /* Assertion assertion = wasresponse.getAssertion(); */ - /* System.out.println("ID: " + assertion.getID()); */ - /* System.out.println("UserID: " + assertion.getUserID()); */ - /* System.out.println("NameID: " + assertion.getNameID()); */ - /* System.out.println("GroupID: " + assertion.getGroupID()); */ - /* System.out.println("GroupName: " + assertion.getGroupName()); */ - /* System.out.println("From: " + assertion.getFrom()); */ - /* System.out.println("Until: " + assertion.getUntil()); */ - /* for(String role : assertion.getRoles()) { */ - /* System.out.println("Role: " + role); */ - /* } */ - /* Signature signature = assertion.getSiganture(); */ - /* System.out.println("Cert:"); */ - /* System.out.println(signature.getCertificate()); */ - /* System.out.println("Value: " + signature.getValue()); */ - /* System.out.println("Digest: " + signature.getDigestValue()); */ - /* System.out.println("Reference: " + signature.getReference()); */ - } - catch(ServiceException e) { + catch(AuthenticationException e) { //TODO User could not be authenticated throw new ServletException(e); } - catch(GeneralSecurityException e) { - throw new ServletException(e); - } } - private Response auth(String username, String password, String encoding) - throws IOException, ServiceException, GeneralSecurityException { - SSLSocketFactory sf = new SSLSocketFactory( - new GGInATrustStrategy()); - Scheme https = new Scheme("https", 443, sf); - HttpClient httpclient = new DefaultHttpClient(); - httpclient.getConnectionManager().getSchemeRegistry().register(https); - - Request httpget = new Request("https://geoportal.bafg.de/" + - "administration/WAS", username, password, encoding); - HttpResponse response = httpclient.execute(httpget); - HttpEntity entity = response.getEntity(); - if (entity == null) { - return null; - } - else { - return new Response(entity); - } + private Authentication auth(String username, String password, String encoding) + throws AuthenticationException, IOException { + String auth = this.getInitParameter("authentication"); + return AuthenticationFactory.getInstance(auth).auth(username, password, encoding); } } diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/Authentication.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/Authentication.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,16 @@ +package de.intevation.flys.client.server.auth; + +import de.intevation.flys.client.server.auth.User; +/** Interface to represent user authentications + */ +public interface Authentication { + + /** Returns true if the authentication was successfull + */ + public boolean isSuccess(); + + /** Returns a new User object + */ + public User getUser(); + +} diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/AuthenticationException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/AuthenticationException.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,19 @@ +package de.intevation.flys.client.server.auth; + +import java.lang.Exception; + +/** + * Base class for Authentication related Exceptions + */ +public class AuthenticationException extends Exception { + + public AuthenticationException(String message) { + super(message); + } + + public AuthenticationException(Exception e) { + super(e); + } +} +// vim: set fileencoding=utf-8 ts=4 sw=4 tw=80: + diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/AuthenticationFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/AuthenticationFactory.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,15 @@ +package de.intevation.flys.client.server.auth; + +import java.lang.IllegalArgumentException; + +public class AuthenticationFactory { + + public static Authenticator getInstance(String name) + throws IllegalArgumentException { + if (name == null || name.equalsIgnoreCase("was") || + name.equalsIgnoreCase("ggina")) { + return new de.intevation.flys.client.server.auth.was.Authenticator(); + } + throw new IllegalArgumentException("Unkown Authentication " + name); + } +} diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/Authenticator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/Authenticator.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,14 @@ +package de.intevation.flys.client.server.auth; + +import java.io.IOException; + +import de.intevation.flys.client.server.auth.Authentication; +import de.intevation.flys.client.server.auth.AuthenticationException; + +public interface Authenticator { + + public Authentication auth(String username, String password, String encoding) + throws AuthenticationException, IOException; + +} + diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/User.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/User.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,11 @@ +package de.intevation.flys.client.server.auth; + +public interface User { + + public String getName(); + + public String getPassword(); + + public Boolean hasExpired(); +} +// vim:set ts=4 sw=4 si et fenc=utf8 tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Assertion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Assertion.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,178 @@ +package de.intevation.flys.client.server.auth.was; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Iterator; +import java.util.Date; +import java.util.List; +import java.util.LinkedList; + +import org.apache.log4j.Logger; + +import org.jdom.Element; + +public class Assertion { + + private static Logger logger = Logger.getLogger(Assertion.class); + + private Element assertion; + private LinkedList roles; + private String assertion_id; + private String user_id; + private String name_id; + private String group_id; + private String group_name; + private Date notbefore; + private Date notonorafter; + private Signature signature; + + private static final String ATTR_CONT_USER_ID = + "urn:conterra:names:sdi-suite:policy:attribute:user-id"; + private static final String ATTR_CONT_GROUP_ID = + "urn:conterra:names:sdi-suite:policy:attribute:group-id"; + private static final String ATTR_CONT_GROUP_NAME = + "urn:conterra:names:sdi-suite:policy:attribute:group-name"; + private static final String ATTR_CONT_ROLE = + "urn:conterra:names:sdi-suite:policy:attribute:role"; + + + public Assertion(Element assertion) { + this.assertion = assertion; + this.roles = new LinkedList(); + + this.assertion_id = assertion.getAttributeValue("AssertionID"); + + this.parseContition(); + this.parseAttributeStatement(); + } + + private void parseContition() { + Element condition = this.assertion.getChild("Conditions", + Namespaces.SAML_NS_ASSERT); + if (condition != null) { + SimpleDateFormat dateformat = new SimpleDateFormat(); + // format should be "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" but that's only + // available in java 7+ + dateformat.applyPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + String from = condition.getAttributeValue("NotBefore"); + if (from != null) { + try { + this.notbefore = dateformat.parse(from); + } + catch(ParseException e) { + logger.error("Unknown datetime format for Condition " + + "NotBefore " + from); + } + } + + String until = condition.getAttributeValue("NotOnOrAfter"); + if (until != null) { + try { + this.notonorafter = dateformat.parse(until); + } + catch(ParseException e) { + logger.error("Unknown datetime format for Condition " + + "NotOnOrAfter " + until); + } + } + } + } + + private void parseAttributeStatement() { + Element attrstatement = this.assertion.getChild("AttributeStatement", + Namespaces.SAML_NS_ASSERT); + if (attrstatement != null) { + + Element subject = attrstatement.getChild("Subject", + Namespaces.SAML_NS_ASSERT); + if (subject != null) { + this.name_id = subject.getChildText("NameIdentifier", + Namespaces.SAML_NS_ASSERT); + } + + List attributes = attrstatement.getChildren("Attribute", + Namespaces.SAML_NS_ASSERT); + for(Iterator i = attributes.iterator(); i.hasNext();) { + Element attr = (Element)i.next(); + String attrname = attr.getAttributeValue("AttributeName"); + if (attrname.equals(ATTR_CONT_USER_ID)) { + this.user_id = this.getAttributeValue(attr); + } + else if (attrname.equals(ATTR_CONT_GROUP_ID)) { + this.group_id = this.getAttributeValue(attr); + } + else if (attrname.equals(ATTR_CONT_GROUP_NAME)) { + this.group_name = this.getAttributeValue(attr); + } + else if (attrname.equals(ATTR_CONT_ROLE)) { + List roles = attr.getChildren("AttributeValue", + Namespaces.SAML_NS_ASSERT); + for(Iterator j = roles.iterator(); j.hasNext();) { + Element role = (Element)j.next(); + this.roles.add(role.getText()); + } + } + else { + logger.debug("Unknown AttributeName " + attrname + + " found while parsing AttributeStatement."); + } + } + } + } + + private String getAttributeValue(Element attr) { + return attr.getChildText("AttributeValue", Namespaces.SAML_NS_ASSERT); + } + + public List getRoles() { + return this.roles; + } + + public Boolean isValid() { + // TODO: + // check signature digest + // check signature value + // check signature cert + return false; + } + + public Signature getSiganture() { + if (this.signature == null) { + Element signature = this.assertion.getChild("Signature", + Namespaces.XML_SIG_NS); + if (signature != null) { + this.signature = new Signature(signature); + } + } + return this.signature; + } + + public String getUserID() { + return this.user_id; + } + + public String getNameID() { + return this.name_id; + } + + public String getGroupID() { + return this.group_id; + } + + public String getGroupName() { + return this.group_name; + } + + public String getID() { + return this.assertion_id; + } + + public Date getFrom() { + return this.notbefore; + } + + public Date getUntil() { + return this.notonorafter; + } +} +// vim: set fileencoding=utf-8 ts=4 sw=4 et si tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Authenticator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Authenticator.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,44 @@ +package de.intevation.flys.client.server.auth.was; + +import java.io.IOException; +import java.security.GeneralSecurityException; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.impl.client.DefaultHttpClient; + +import de.intevation.flys.client.server.GGInATrustStrategy; +import de.intevation.flys.client.server.auth.Authentication; +import de.intevation.flys.client.server.auth.AuthenticationException; + +public class Authenticator implements de.intevation.flys.client.server.auth.Authenticator { + + public Authentication auth(String username, String password, String encoding) + throws AuthenticationException, IOException { + try { + SSLSocketFactory sf = new SSLSocketFactory( + new GGInATrustStrategy()); + Scheme https = new Scheme("https", 443, sf); + HttpClient httpclient = new DefaultHttpClient(); + httpclient.getConnectionManager().getSchemeRegistry().register(https); + + Request httpget = new Request("https://geoportal.bafg.de/" + + "administration/WAS", username, password, encoding); + HttpResponse response = httpclient.execute(httpget); + HttpEntity entity = response.getEntity(); + if (entity == null) { + //FIXME throw AuthenticationException + return null; + } + else { + return new Response(entity, username, password); + } + } + catch(GeneralSecurityException e) { + throw new AuthenticationException(e); + } + } +} diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Namespaces.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Namespaces.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,14 @@ +package de.intevation.flys.client.server.auth.was; + +import org.jdom.Namespace; + +public class Namespaces { + + public static final Namespace SAML_NS_ASSERT = + Namespace.getNamespace("urn:oasis:names:tc:SAML:1.0:assertion"); + public static final Namespace SAML_NS_PROTO = + Namespace.getNamespace("urn:oasis:names:tc:SAML:1.0:protocol"); + public static final Namespace XML_SIG_NS = + Namespace.getNamespace("http://www.w3.org/2000/09/xmldsig#"); + +} diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Request.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Request.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,61 @@ +package de.intevation.flys.client.server.auth.was; + +import java.io.UnsupportedEncodingException; +import java.net.URI; + +import org.apache.commons.codec.binary.Base64; +import org.apache.http.client.methods.HttpGet; +import org.apache.log4j.Logger; + +public class Request extends HttpGet { + + private final static String VERSION = "1.1"; + private final static String REQUEST_SAML_RESPONSE = "GetSAMLResponse"; + private final static String METHOD_AUTH_PASSWORD = + "urn:opengeospatial:authNMethod:OWS:1.0:password"; + + private static Logger logger = Logger.getLogger(Request.class); + + public Request(String uri) { + String request = uri + "?VERSION=" + VERSION + "&REQUEST=" + + REQUEST_SAML_RESPONSE + "&METHOD=" + METHOD_AUTH_PASSWORD + + "&ANONYMOUS=TRUE&CREDENTIALS="; + this.setURI(URI.create(request)); + } + + public Request(String uri, String user, String pass, String encoding) { + try { + String base64user = this.toBase64(user, encoding); + String base64pass = this.toBase64(pass, encoding); + + String request = uri + "?VERSION=" + VERSION + "&REQUEST=" + + REQUEST_SAML_RESPONSE + "&METHOD=" + METHOD_AUTH_PASSWORD + + "&CREDENTIALS=" + base64user + "," + base64pass; + + System.out.println(request); + + this.setURI(URI.create(request)); + } + catch(UnsupportedEncodingException e) { + logger.error(e); + } + } + + private String toBase64(String value, String encoding) throws + UnsupportedEncodingException { + if (encoding == null) { + encoding = "utf-8"; + } + try { + return new String(Base64.encodeBase64(value.getBytes(encoding))); + } + catch(UnsupportedEncodingException e) { + logger.warn("Can't encode string with encoding " + encoding + + ". Falling back to utf-8. " + e); + return this.toBase64(value, "utf-8"); + } + } + +} +// vim: set et si fileencoding=utf-8 ts=4 sw=4 tw=80: + diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Response.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Response.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,105 @@ +package de.intevation.flys.client.server.auth.was; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.codec.binary.Base64InputStream; + +import org.apache.http.HttpEntity; + +import org.apache.log4j.Logger; + +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.input.SAXBuilder; + +import de.intevation.flys.client.server.auth.Authentication; + +public class Response implements Authentication { + + private static Logger logger = Logger.getLogger(Response.class); + + private Element root; + private Assertion assertion; + private String username; + private String password; + + + public Response(HttpEntity entity, String username, String password) throws ServiceException { + + if (entity == null) { + throw new ServiceException("Invalid response"); + } + + String contenttype = entity.getContentType().getValue(); + + try { + InputStream in = entity.getContent(); + + if (!contenttype.equals("application/vnd.ogc.se_xml")) { + // XXX: Assume base64 encoded content. + in = new Base64InputStream(in); + } + + SAXBuilder builder = new SAXBuilder(); + Document doc = builder.build(in); + Element root = doc.getRootElement(); + String rname = root.getName(); + + if (rname != null && rname.equals("ServiceExceptionReport")) { + throw new ServiceException(root.getChildText("ServiceException")); + } + + this.root = root; + this.username = username; + this.password = password; + + } + catch(JDOMException e) { + logger.error(e); + } + catch(IOException e) { + logger.error(e); + } + } + + public Element getRoot() { + return this.root; + } + + @Override + public boolean isSuccess() { + String status = getStatus(); + return status != null && status.equals("samlp:Success"); + } + + public String getStatus() { + Element status = this.root.getChild("Status", Namespaces.SAML_NS_PROTO); + if (status == null) { + return null; + } + Element statuscode = status.getChild("StatusCode", + Namespaces.SAML_NS_PROTO); + if (statuscode == null) { + return null; + } + return statuscode.getAttributeValue("Value"); + } + + public Assertion getAssertion() { + if (this.assertion == null && this.root != null) { + Element assertion = this.root.getChild("Assertion", + Namespaces.SAML_NS_ASSERT); + if (assertion != null) { + this.assertion = new Assertion(assertion); + } + } + return this.assertion; + } + + public User getUser() { + return new User(this.username, this.password); + } +} +// vim: set si et fileencoding=utf-8 ts=4 sw=4 tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/was/ServiceException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/was/ServiceException.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,17 @@ +package de.intevation.flys.client.server.auth.was; + +import java.lang.Exception; + +import de.intevation.flys.client.server.auth.AuthenticationException; + +public class ServiceException extends AuthenticationException { + + public ServiceException(String message) { + super(message); + } + + public ServiceException(Exception e) { + super(e); + } +} +// vim: set si et fileencoding=utf-8 ts=4 sw=4 tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Signature.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/was/Signature.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,121 @@ +package de.intevation.flys.client.server.auth.was; + +import java.io.ByteArrayInputStream; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; + +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; + +import org.jdom.Element; + +public class Signature { + + private static Logger logger = Logger.getLogger(Signature.class); + + private static final String XML_SIG_DIGEST_SHA1 = + "http://www.w3.org/2000/09/xmldsig#sha1"; + private static final String XML_SIG_SIGNATURE_RSA_SHA1 = + "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; + + private Element signature; + private Certificate cert; + private byte[] value; + private byte[] digestvalue; + private String reference; + + public Signature(Element signature) { + this.signature = signature; + this.parseSignatureInfo(); + this.parseSignatureValue(); + this.parseCertificate(); + } + + private void parseSignatureInfo() { + Element signatureinfo = this.signature.getChild("SignedInfo", + Namespaces.XML_SIG_NS); + if (signatureinfo != null) { + Element signaturemethod = signatureinfo.getChild("SignatureMethod", + Namespaces.XML_SIG_NS); + String algorithm = signaturemethod.getAttributeValue("Algorithm"); + if (!algorithm.equals(XML_SIG_SIGNATURE_RSA_SHA1)) { + logger.warn("Unkown signature alorithm " + algorithm); + } + + // There could be several references in XML-Sig spec but for me it + // doesn't make sense to have more then one in a SAML Assertion + Element reference = signatureinfo.getChild("Reference", + Namespaces.XML_SIG_NS); + // reference must be present but its better to check + if (reference != null) { + String digestvalue = reference.getChildText("DigestValue", + Namespaces.XML_SIG_NS); + String digestmethod = reference.getChildText("DigestMethod", + Namespaces.XML_SIG_NS); + if (!digestmethod.equals(XML_SIG_DIGEST_SHA1)) { + logger.warn("Unknown digest method " + digestmethod); + } + this.digestvalue = Base64.decodeBase64(digestvalue); + + String referenceuri = reference.getAttributeValue("URI"); + if (referenceuri.startsWith("#")) { + this.reference = referenceuri.substring(1); + } + else { + logger.warn("Unkown reference type " + referenceuri); + this.reference = referenceuri; + } + } + } + } + + private void parseSignatureValue() { + String signaturevalue = this.signature.getChildText("SignatureValue", + Namespaces.XML_SIG_NS); + this.value = Base64.decodeBase64(signaturevalue); + } + + private void parseCertificate() { + Element keyinfo = this.signature.getChild("KeyInfo", + Namespaces.XML_SIG_NS); + if (keyinfo != null) { + Element data = keyinfo.getChild("X509Data", Namespaces.XML_SIG_NS); + if (data != null) { + String base64cert = data.getChildText("X509Certificate", + Namespaces.XML_SIG_NS); + if (base64cert != null) { + byte[] bytes = Base64.decodeBase64(base64cert); + try { + CertificateFactory cf = CertificateFactory.getInstance( + "X.509"); + this.cert = cf.generateCertificate( + new ByteArrayInputStream(bytes)); + } + catch(CertificateException e) { + // should never occur + logger.error(e); + } + } + } + } + } + + public Certificate getCertificate() { + return this.cert; + } + + public byte[] getValue() { + return this.value; + } + + public String getReference() { + // In theory there could be several references with digestvalues, ... + return this.reference; + } + + public byte[] getDigestValue() { + return this.digestvalue; + } +} +// vim: set si et fileencoding=utf-8 ts=4 sw=4 tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/auth/was/User.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/auth/was/User.java Wed Jul 11 13:31:56 2012 +0000 @@ -0,0 +1,24 @@ +package de.intevation.flys.client.server.auth.was; + +import de.intevation.flys.client.shared.model.DefaultUser; + +public class User extends DefaultUser implements de.intevation.flys.client.server.auth.User { + + private String password; + + public User(String name, String password) { + this.setName(name); + this.password = password; + } + + public String getPassword() { + return this.password; + } + + public Boolean hasExpired() { + //TODO + return false; + } +} + +// vim:set ts=4 sw=4 si et fenc=utf8 tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/was/Assertion.java --- a/flys-client/src/main/java/de/intevation/flys/client/server/was/Assertion.java Wed Jul 11 12:34:26 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ -package de.intevation.flys.client.server.was; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Iterator; -import java.util.Date; -import java.util.List; -import java.util.LinkedList; - -import org.apache.log4j.Logger; - -import org.jdom.Element; - -public class Assertion { - - private static Logger logger = Logger.getLogger(Assertion.class); - - private Element assertion; - private LinkedList roles; - private String assertion_id; - private String user_id; - private String name_id; - private String group_id; - private String group_name; - private Date notbefore; - private Date notonorafter; - private Signature signature; - - private static final String ATTR_CONT_USER_ID = - "urn:conterra:names:sdi-suite:policy:attribute:user-id"; - private static final String ATTR_CONT_GROUP_ID = - "urn:conterra:names:sdi-suite:policy:attribute:group-id"; - private static final String ATTR_CONT_GROUP_NAME = - "urn:conterra:names:sdi-suite:policy:attribute:group-name"; - private static final String ATTR_CONT_ROLE = - "urn:conterra:names:sdi-suite:policy:attribute:role"; - - - public Assertion(Element assertion) { - this.assertion = assertion; - this.roles = new LinkedList(); - - this.assertion_id = assertion.getAttributeValue("AssertionID"); - - this.parseContition(); - this.parseAttributeStatement(); - } - - private void parseContition() { - Element condition = this.assertion.getChild("Conditions", - Namespaces.SAML_NS_ASSERT); - if (condition != null) { - SimpleDateFormat dateformat = new SimpleDateFormat(); - // format should be "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" but that's only - // available in java 7+ - dateformat.applyPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); - String from = condition.getAttributeValue("NotBefore"); - if (from != null) { - try { - this.notbefore = dateformat.parse(from); - } - catch(ParseException e) { - logger.error("Unknown datetime format for Condition " + - "NotBefore " + from); - } - } - - String until = condition.getAttributeValue("NotOnOrAfter"); - if (until != null) { - try { - this.notonorafter = dateformat.parse(until); - } - catch(ParseException e) { - logger.error("Unknown datetime format for Condition " + - "NotOnOrAfter " + until); - } - } - } - } - - private void parseAttributeStatement() { - Element attrstatement = this.assertion.getChild("AttributeStatement", - Namespaces.SAML_NS_ASSERT); - if (attrstatement != null) { - - Element subject = attrstatement.getChild("Subject", - Namespaces.SAML_NS_ASSERT); - if (subject != null) { - this.name_id = subject.getChildText("NameIdentifier", - Namespaces.SAML_NS_ASSERT); - } - - List attributes = attrstatement.getChildren("Attribute", - Namespaces.SAML_NS_ASSERT); - for(Iterator i = attributes.iterator(); i.hasNext();) { - Element attr = (Element)i.next(); - String attrname = attr.getAttributeValue("AttributeName"); - if (attrname.equals(ATTR_CONT_USER_ID)) { - this.user_id = this.getAttributeValue(attr); - } - else if (attrname.equals(ATTR_CONT_GROUP_ID)) { - this.group_id = this.getAttributeValue(attr); - } - else if (attrname.equals(ATTR_CONT_GROUP_NAME)) { - this.group_name = this.getAttributeValue(attr); - } - else if (attrname.equals(ATTR_CONT_ROLE)) { - List roles = attr.getChildren("AttributeValue", - Namespaces.SAML_NS_ASSERT); - for(Iterator j = roles.iterator(); j.hasNext();) { - Element role = (Element)j.next(); - this.roles.add(role.getText()); - } - } - else { - logger.debug("Unknown AttributeName " + attrname + - " found while parsing AttributeStatement."); - } - } - } - } - - private String getAttributeValue(Element attr) { - return attr.getChildText("AttributeValue", Namespaces.SAML_NS_ASSERT); - } - - public List getRoles() { - return this.roles; - } - - public Boolean isValid() { - // TODO: - // check signature digest - // check signature value - // check signature cert - return false; - } - - public Signature getSiganture() { - if (this.signature == null) { - Element signature = this.assertion.getChild("Signature", - Namespaces.XML_SIG_NS); - if (signature != null) { - this.signature = new Signature(signature); - } - } - return this.signature; - } - - public String getUserID() { - return this.user_id; - } - - public String getNameID() { - return this.name_id; - } - - public String getGroupID() { - return this.group_id; - } - - public String getGroupName() { - return this.group_name; - } - - public String getID() { - return this.assertion_id; - } - - public Date getFrom() { - return this.notbefore; - } - - public Date getUntil() { - return this.notonorafter; - } -} -// vim: set fileencoding=utf-8 ts=4 sw=4 et si tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/was/Namespaces.java --- a/flys-client/src/main/java/de/intevation/flys/client/server/was/Namespaces.java Wed Jul 11 12:34:26 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -package de.intevation.flys.client.server.was; - -import org.jdom.Namespace; - -public class Namespaces { - - public static final Namespace SAML_NS_ASSERT = - Namespace.getNamespace("urn:oasis:names:tc:SAML:1.0:assertion"); - public static final Namespace SAML_NS_PROTO = - Namespace.getNamespace("urn:oasis:names:tc:SAML:1.0:protocol"); - public static final Namespace XML_SIG_NS = - Namespace.getNamespace("http://www.w3.org/2000/09/xmldsig#"); - -} diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/was/Request.java --- a/flys-client/src/main/java/de/intevation/flys/client/server/was/Request.java Wed Jul 11 12:34:26 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package de.intevation.flys.client.server.was; - -import java.io.UnsupportedEncodingException; -import java.net.URI; - -import org.apache.commons.codec.binary.Base64; -import org.apache.http.client.methods.HttpGet; -import org.apache.log4j.Logger; - -public class Request extends HttpGet { - - private final static String VERSION = "1.1"; - private final static String REQUEST_SAML_RESPONSE = "GetSAMLResponse"; - private final static String METHOD_AUTH_PASSWORD = - "urn:opengeospatial:authNMethod:OWS:1.0:password"; - - private static Logger logger = Logger.getLogger(Request.class); - - public Request(String uri) { - String request = uri + "?VERSION=" + VERSION + "&REQUEST=" + - REQUEST_SAML_RESPONSE + "&METHOD=" + METHOD_AUTH_PASSWORD + - "&ANONYMOUS=TRUE&CREDENTIALS="; - this.setURI(URI.create(request)); - } - - public Request(String uri, String user, String pass, String encoding) { - try { - String base64user = this.toBase64(user, encoding); - String base64pass = this.toBase64(pass, encoding); - - String request = uri + "?VERSION=" + VERSION + "&REQUEST=" + - REQUEST_SAML_RESPONSE + "&METHOD=" + METHOD_AUTH_PASSWORD + - "&CREDENTIALS=" + base64user + "," + base64pass; - - System.out.println(request); - - this.setURI(URI.create(request)); - } - catch(UnsupportedEncodingException e) { - logger.error(e); - } - } - - private String toBase64(String value, String encoding) throws - UnsupportedEncodingException { - if (encoding == null) { - encoding = "utf-8"; - } - try { - return new String(Base64.encodeBase64(value.getBytes(encoding))); - } - catch(UnsupportedEncodingException e) { - logger.warn("Can't encode string with encoding " + encoding + - ". Falling back to utf-8. " + e); - return this.toBase64(value, "utf-8"); - } - } - -} -// vim: set et si fileencoding=utf-8 ts=4 sw=4 tw=80: - diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/was/Response.java --- a/flys-client/src/main/java/de/intevation/flys/client/server/was/Response.java Wed Jul 11 12:34:26 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -package de.intevation.flys.client.server.was; - -import java.io.IOException; -import java.io.InputStream; - -import org.apache.commons.codec.binary.Base64InputStream; - -import org.apache.http.HttpEntity; - -import org.apache.log4j.Logger; - -import org.jdom.Document; -import org.jdom.Element; -import org.jdom.JDOMException; - -import org.jdom.input.SAXBuilder; - -public class Response { - - private static Logger logger = Logger.getLogger(Response.class); - - private Element root; - private Assertion assertion; - - public Response(HttpEntity entity) throws ServiceException { - - if (entity == null) { - throw new ServiceException("Invalid response"); - } - - String contenttype = entity.getContentType().getValue(); - - try { - InputStream in = entity.getContent(); - - if (!contenttype.equals("application/vnd.ogc.se_xml")) { - // XXX: Assume base64 encoded content. - in = new Base64InputStream(in); - } - - SAXBuilder builder = new SAXBuilder(); - Document doc = builder.build(in); - Element root = doc.getRootElement(); - String rname = root.getName(); - - if (rname != null && rname.equals("ServiceExceptionReport")) { - throw new ServiceException(root.getChildText("ServiceException")); - } - - this.root = root; - } - catch(JDOMException e) { - logger.error(e); - } - catch(IOException e) { - logger.error(e); - } - } - - public Element getRoot() { - return this.root; - } - - public Boolean isSuccess() { - String status = getStatus(); - return status != null && status.equals("samlp:Success"); - } - - public String getStatus() { - Element status = this.root.getChild("Status", Namespaces.SAML_NS_PROTO); - if (status == null) { - return null; - } - Element statuscode = status.getChild("StatusCode", - Namespaces.SAML_NS_PROTO); - if (statuscode == null) { - return null; - } - return statuscode.getAttributeValue("Value"); - } - - public Assertion getAssertion() { - if (this.assertion == null && this.root != null) { - Element assertion = this.root.getChild("Assertion", - Namespaces.SAML_NS_ASSERT); - if (assertion != null) { - this.assertion = new Assertion(assertion); - } - } - return this.assertion; - } -} -// vim: set si et fileencoding=utf-8 ts=4 sw=4 tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/was/ServiceException.java --- a/flys-client/src/main/java/de/intevation/flys/client/server/was/ServiceException.java Wed Jul 11 12:34:26 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -package de.intevation.flys.client.server.was; - -import java.lang.Exception; - -public class ServiceException extends Exception { - - public ServiceException(String message) { - super(message); - } -} -// vim: set si et fileencoding=utf-8 ts=4 sw=4 tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/was/Signature.java --- a/flys-client/src/main/java/de/intevation/flys/client/server/was/Signature.java Wed Jul 11 12:34:26 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -package de.intevation.flys.client.server.was; - -import java.io.ByteArrayInputStream; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; - -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - -import org.jdom.Element; - -public class Signature { - - private static Logger logger = Logger.getLogger(Signature.class); - - private static final String XML_SIG_DIGEST_SHA1 = - "http://www.w3.org/2000/09/xmldsig#sha1"; - private static final String XML_SIG_SIGNATURE_RSA_SHA1 = - "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; - - private Element signature; - private Certificate cert; - private byte[] value; - private byte[] digestvalue; - private String reference; - - public Signature(Element signature) { - this.signature = signature; - this.parseSignatureInfo(); - this.parseSignatureValue(); - this.parseCertificate(); - } - - private void parseSignatureInfo() { - Element signatureinfo = this.signature.getChild("SignedInfo", - Namespaces.XML_SIG_NS); - if (signatureinfo != null) { - Element signaturemethod = signatureinfo.getChild("SignatureMethod", - Namespaces.XML_SIG_NS); - String algorithm = signaturemethod.getAttributeValue("Algorithm"); - if (!algorithm.equals(XML_SIG_SIGNATURE_RSA_SHA1)) { - logger.warn("Unkown signature alorithm " + algorithm); - } - - // There could be several references in XML-Sig spec but for me it - // doesn't make sense to have more then one in a SAML Assertion - Element reference = signatureinfo.getChild("Reference", - Namespaces.XML_SIG_NS); - // reference must be present but its better to check - if (reference != null) { - String digestvalue = reference.getChildText("DigestValue", - Namespaces.XML_SIG_NS); - String digestmethod = reference.getChildText("DigestMethod", - Namespaces.XML_SIG_NS); - if (!digestmethod.equals(XML_SIG_DIGEST_SHA1)) { - logger.warn("Unknown digest method " + digestmethod); - } - this.digestvalue = Base64.decodeBase64(digestvalue); - - String referenceuri = reference.getAttributeValue("URI"); - if (referenceuri.startsWith("#")) { - this.reference = referenceuri.substring(1); - } - else { - logger.warn("Unkown reference type " + referenceuri); - this.reference = referenceuri; - } - } - } - } - - private void parseSignatureValue() { - String signaturevalue = this.signature.getChildText("SignatureValue", - Namespaces.XML_SIG_NS); - this.value = Base64.decodeBase64(signaturevalue); - } - - private void parseCertificate() { - Element keyinfo = this.signature.getChild("KeyInfo", - Namespaces.XML_SIG_NS); - if (keyinfo != null) { - Element data = keyinfo.getChild("X509Data", Namespaces.XML_SIG_NS); - if (data != null) { - String base64cert = data.getChildText("X509Certificate", - Namespaces.XML_SIG_NS); - if (base64cert != null) { - byte[] bytes = Base64.decodeBase64(base64cert); - try { - CertificateFactory cf = CertificateFactory.getInstance( - "X.509"); - this.cert = cf.generateCertificate( - new ByteArrayInputStream(bytes)); - } - catch(CertificateException e) { - // should never occur - logger.error(e); - } - } - } - } - } - - public Certificate getCertificate() { - return this.cert; - } - - public byte[] getValue() { - return this.value; - } - - public String getReference() { - // In theory there could be several references with digestvalues, ... - return this.reference; - } - - public byte[] getDigestValue() { - return this.digestvalue; - } -} -// vim: set si et fileencoding=utf-8 ts=4 sw=4 tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/java/de/intevation/flys/client/server/was/User.java --- a/flys-client/src/main/java/de/intevation/flys/client/server/was/User.java Wed Jul 11 12:34:26 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package de.intevation.flys.client.server.was; - -import de.intevation.flys.client.shared.model.DefaultUser; - -public class User extends DefaultUser { - - private String password; - - public User(String name, String password) { - this.setName(name); - this.password = password; - } - - public String getPassword() { - return this.password; - } - - public Boolean hasExpired() { - //TODO - return false; - } -} - -// vim:set ts=4 sw=4 si et fenc=utf8 tw=80: diff -r f1030909eeb6 -r d7f76f197d89 flys-client/src/main/webapp/WEB-INF/web.xml --- a/flys-client/src/main/webapp/WEB-INF/web.xml Wed Jul 11 12:34:26 2012 +0000 +++ b/flys-client/src/main/webapp/WEB-INF/web.xml Wed Jul 11 13:31:56 2012 +0000 @@ -481,6 +481,10 @@ login de.intevation.flys.client.server.LoginServlet + + authentication + GGInA + @@ -493,7 +497,7 @@ de.intevation.flys.client.server.GGInAFilter deactivate - 0 + false