diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipalImpl.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipalImpl.java index c7ca08f..acc9823 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipalImpl.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipalImpl.java @@ -30,7 +30,6 @@ import java.util.Map; * Concrete implementation of the AttributePrincipal interface. * * @author Scott Battaglia - * @version $Revision$ $Date$ * @since 3.1 */ public class AttributePrincipalImpl extends SimplePrincipal implements AttributePrincipal { @@ -80,7 +79,7 @@ public class AttributePrincipalImpl extends SimplePrincipal implements Attribute } /** - * Constructs a new principal witht he supplied name, attributes, and proxying capabilities. + * Constructs a new principal with the supplied name, attributes, and proxying capabilities. * * @param name the unique identifier for the principal. * @param attributes the key/value pairs for this principal. diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/Cas20ProxyRetriever.java b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/Cas20ProxyRetriever.java index 2910f5f..a77b11f 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/Cas20ProxyRetriever.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/Cas20ProxyRetriever.java @@ -18,33 +18,35 @@ */ package org.jasig.cas.client.proxy; +import org.jasig.cas.client.ssl.HttpURLConnectionFactory; import org.jasig.cas.client.util.CommonUtils; import org.jasig.cas.client.util.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; import java.net.URLEncoder; /** * Implementation of a ProxyRetriever that follows the CAS 2.0 specification. * For more information on the CAS 2.0 specification, please see the specification + * href="http://www.jasig.org/cas/protocol">specification * document. *
* In general, this class will make a call to the CAS server with some specified * parameters and receive an XML response to parse. * * @author Scott Battaglia - * @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $ * @since 3.0 */ public final class Cas20ProxyRetriever implements ProxyRetriever { /** Unique Id for serialization. */ - private static final long serialVersionUID = 560409469568911791L; + private static final long serialVersionUID = 560409469568911791L; - /** + /** * Instance of Commons Logging. */ private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -56,39 +58,45 @@ public final class Cas20ProxyRetriever implements ProxyRetriever { private final String encoding; + /** Url connection factory to use when communicating with the server **/ + private final HttpURLConnectionFactory urlConnectionFactory; + /** * Main Constructor. * * @param casServerUrl the URL to the CAS server (i.e. http://localhost/cas/) * @param encoding the encoding to use. + * @param urlFactory url connection factory use when retrieving proxy responses from the server */ - public Cas20ProxyRetriever(final String casServerUrl, final String encoding) { + public Cas20ProxyRetriever(final String casServerUrl, final String encoding, final HttpURLConnectionFactory urlFactory) { CommonUtils.assertNotNull(casServerUrl, "casServerUrl cannot be null."); this.casServerUrl = casServerUrl; this.encoding = encoding; + this.urlConnectionFactory = urlFactory; } - - public String getProxyTicketIdFor(final String proxyGrantingTicketId, - final String targetService) { - - final String url = constructUrl(proxyGrantingTicketId, targetService); - final String response = CommonUtils.getResponseFromServer(url, this.encoding); + + public String getProxyTicketIdFor(final String proxyGrantingTicketId, final String targetService) { + CommonUtils.assertNotNull(proxyGrantingTicketId, "proxyGrantingTicketId cannot be null."); + CommonUtils.assertNotNull(targetService, "targetService cannot be null."); + + final URL url = constructUrl(proxyGrantingTicketId, targetService); + final String response = CommonUtils.getResponseFromServer(url, this.urlConnectionFactory, this.encoding); final String error = XmlUtils.getTextForElement(response, "proxyFailure"); - + if (CommonUtils.isNotEmpty(error)) { logger.debug(error); return null; } - + return XmlUtils.getTextForElement(response, "proxyTicket"); } - private String constructUrl(final String proxyGrantingTicketId, final String targetService) { + private URL constructUrl(final String proxyGrantingTicketId, final String targetService) { try { - return this.casServerUrl + (this.casServerUrl.endsWith("/") ? "" : "/") + "proxy" + "?pgt=" - + proxyGrantingTicketId + "&targetService=" - + URLEncoder.encode(targetService, "UTF-8"); - } catch (final UnsupportedEncodingException e) { + return new URL(this.casServerUrl + (this.casServerUrl.endsWith("/") ? "" : "/") + "proxy" + + "?pgt=" + proxyGrantingTicketId + + "&targetService=" + URLEncoder.encode(targetService, "UTF-8")); + } catch (final Exception e) { throw new RuntimeException(e); } } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpURLConnectionFactory.java b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpURLConnectionFactory.java new file mode 100644 index 0000000..c3a33ce --- /dev/null +++ b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpURLConnectionFactory.java @@ -0,0 +1,45 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.ssl; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; + +/** + * A factory to prepare and configure {@link java.net.URLConnection} instances. + * + * @author Misagh Moayyed + * @since 3.3 + */ +public interface HttpURLConnectionFactory { + + /** + * Receives a {@link URLConnection} instance typically as a result of a {@link URL} + * opening a connection to a remote resource. The received url connection is then + * configured and prepared appropriately depending on its type and is then returned to the caller + * to accommodate method chaining. + * + * @param url The url connection that needs to be configured + * @return The configured {@link HttpURLConnection} instance + * + * @see {@link HttpsURLConnectionFactory} + */ + HttpURLConnection buildHttpURLConnection(final URLConnection url); +} diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpsURLConnectionFactory.java b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpsURLConnectionFactory.java new file mode 100644 index 0000000..298069a --- /dev/null +++ b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpsURLConnectionFactory.java @@ -0,0 +1,134 @@ +package org.jasig.cas.client.ssl; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URLConnection; +import java.security.KeyStore; +import java.util.Properties; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; + +import org.jasig.cas.client.util.CommonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * An implementation of the {@link HttpURLConnectionFactory} whose responsible to configure + * the underlying https connection, if needed, with a given hostname and SSL socket factory based on the + * configuration provided. + * + * @author Misagh Moayyed + * @since 3.3 + * @see #setHostnameVerifier(HostnameVerifier) + * @see #setSSLConfiguration(Properties) + */ +public final class HttpsURLConnectionFactory implements HttpURLConnectionFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(HttpsURLConnectionFactory.class); + + /** + * Hostname verifier used when making an SSL request to the CAS server. + * Defaults to {@link HttpsURLConnection#getDefaultHostnameVerifier()} + */ + private HostnameVerifier hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); + + /** + * Properties file that can contains key/trust info for Client Side Certificates + */ + private Properties sslConfiguration = new Properties(); + + public HttpsURLConnectionFactory() {} + + public HttpsURLConnectionFactory(final HostnameVerifier verifier, final Properties config) { + setHostnameVerifier(verifier); + setSSLConfiguration(config); + } + + public final void setSSLConfiguration(final Properties config) { + this.sslConfiguration = config; + } + + /** + * Set the host name verifier for the https connection received. + * + * @see AnyHostnameVerifier + * @see RegexHostnameVerifier + * @see WhitelistHostnameVerifier + */ + public final void setHostnameVerifier(final HostnameVerifier verifier) { + this.hostnameVerifier = verifier; + } + + public HttpURLConnection buildHttpURLConnection(final URLConnection url) { + return this.configureHttpsConnectionIfNeeded(url); + } + + /** + * Configures the connection with specific settings for secure http connections + * If the connection instance is not a {@link HttpsURLConnection}, + * no additional changes will be made and the connection itself is simply returned. + * + * @param conn the http connection + */ + private HttpURLConnection configureHttpsConnectionIfNeeded(final URLConnection conn) { + if (conn instanceof HttpsURLConnection) { + final HttpsURLConnection httpsConnection = (HttpsURLConnection) conn; + final SSLSocketFactory socketFactory = this.createSSLSocketFactory(); + if (socketFactory != null) { + httpsConnection.setSSLSocketFactory(socketFactory); + } + + if (this.hostnameVerifier != null) { + httpsConnection.setHostnameVerifier(this.hostnameVerifier); + } + } + return (HttpURLConnection) conn; + } + + /** + * Creates a {@link SSLSocketFactory} based on the configuration specified + *+ * Sample properties file: + *
+ * protocol=TLS + * keyStoreType=JKS + * keyStorePath=/var/secure/location/.keystore + * keyStorePass=changeit + * certificatePassword=aGoodPass + *+ * @return the {@link SSLSocketFactory} + */ + private SSLSocketFactory createSSLSocketFactory() { + InputStream keyStoreIS = null; + try { + final SSLContext sslContext = SSLContext.getInstance(this.sslConfiguration.getProperty("protocol", "SSL")); + + if (this.sslConfiguration.getProperty("keyStoreType") != null) { + final KeyStore keyStore = KeyStore.getInstance(this.sslConfiguration.getProperty("keyStoreType")); + if (this.sslConfiguration.getProperty("keyStorePath") != null) { + keyStoreIS = new FileInputStream(this.sslConfiguration.getProperty("keyStorePath")); + if (this.sslConfiguration.getProperty("keyStorePass") != null) { + keyStore.load(keyStoreIS, this.sslConfiguration.getProperty("keyStorePass").toCharArray()); + LOGGER.debug("Keystore has {} keys", keyStore.size()); + final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(this.sslConfiguration.getProperty("keyManagerType", "SunX509")); + keyManager.init(keyStore, this.sslConfiguration.getProperty("certificatePassword").toCharArray()); + sslContext.init(keyManager.getKeyManagers(), null, null); + return sslContext.getSocketFactory(); + } + } + } + + } catch (final Exception e) { + LOGGER.error(e.getMessage(), e); + } finally { + CommonUtils.closeQuietly(keyStoreIS); + } + return null; + } + +} diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java index e9e2183..e242510 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java @@ -67,6 +67,10 @@ public abstract class AbstractConfigurationFilter implements Filter { final String value = filterConfig.getInitParameter(propertyName); if (CommonUtils.isNotBlank(value)) { + if ("renew".equals(propertyName)) { + throw new IllegalArgumentException( + "Renew MUST be specified via context parameter or JNDI environment to avoid misconfiguration."); + } logger.info("Property [{}] loaded from FilterConfig.getInitParameter with value [{}]", propertyName, value); return value; } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java index 91a3aaa..e754941 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java @@ -19,25 +19,27 @@ package org.jasig.cas.client.util; import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; +import org.jasig.cas.client.ssl.HttpsURLConnectionFactory; +import org.jasig.cas.client.ssl.HttpURLConnectionFactory; import org.jasig.cas.client.validation.ProxyList; import org.jasig.cas.client.validation.ProxyListEditor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.Closeable; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.io.BufferedReader; import java.io.InputStreamReader; +import java.net.MalformedURLException; import java.net.URLConnection; import java.net.URLEncoder; import java.net.URL; import java.net.HttpURLConnection; -import java.net.MalformedURLException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; @@ -323,28 +325,16 @@ public final class CommonUtils { * Contacts the remote URL and returns the response. * * @param constructedUrl the url to contact. + * @param factory connection factory to prepare the URL connection instance * @param encoding the encoding to use. * @return the response. */ - public static String getResponseFromServer(final URL constructedUrl, final String encoding) { - return getResponseFromServer(constructedUrl, HttpsURLConnection.getDefaultHostnameVerifier(), encoding); - } + public static String getResponseFromServer(final URL constructedUrl, final HttpURLConnectionFactory factory, final String encoding) { - /** - * Contacts the remote URL and returns the response. - * - * @param constructedUrl the url to contact. - * @param hostnameVerifier Host name verifier to use for HTTPS connections. - * @param encoding the encoding to use. - * @return the response. - */ - public static String getResponseFromServer(final URL constructedUrl, final HostnameVerifier hostnameVerifier, final String encoding) { - URLConnection conn = null; + HttpURLConnection conn = null; try { - conn = constructedUrl.openConnection(); - if (conn instanceof HttpsURLConnection) { - ((HttpsURLConnection)conn).setHostnameVerifier(hostnameVerifier); - } + conn = factory.buildHttpURLConnection(constructedUrl.openConnection()); + final BufferedReader in; if (CommonUtils.isEmpty(encoding)) { @@ -365,27 +355,12 @@ public final class CommonUtils { LOGGER.error(e.getMessage(), e); throw new RuntimeException(e); } finally { - if (conn != null && conn instanceof HttpURLConnection) { - ((HttpURLConnection)conn).disconnect(); + if (conn != null) { + conn.disconnect(); } } - } - /** - * Contacts the remote URL and returns the response. - * - * @param url the url to contact. - * @param encoding the encoding to use. - * @return the response. - */ - public static String getResponseFromServer(final String url, String encoding) { - try { - return getResponseFromServer(new URL(url), encoding); - } catch (final MalformedURLException e) { - throw new IllegalArgumentException(e); - } - } - + public static ProxyList createProxyList(final String proxies) { if (CommonUtils.isBlank(proxies)) { return new ProxyList(); @@ -410,4 +385,19 @@ public final class CommonUtils { } } + + /** + * Unconditionally close a {@link Closeable}. Equivalent to {@link java.io.Closeable#close()}close(), except any exceptions + * will be ignored. This is typically used in finally blocks. + * @param resource + */ + public static void closeQuietly(final Closeable resource) { + try { + if (resource != null) { + resource.close(); + } + } catch (final IOException e) { + //ignore + } + } } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractCasProtocolUrlBasedTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractCasProtocolUrlBasedTicketValidator.java index 7e736d7..c19ec9f 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractCasProtocolUrlBasedTicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractCasProtocolUrlBasedTicketValidator.java @@ -43,10 +43,6 @@ public abstract class AbstractCasProtocolUrlBasedTicketValidator extends Abstrac * Retrieves the response from the server by opening a connection and merely reading the response. */ protected final String retrieveResponseFromServer(final URL validationUrl, final String ticket) { - if (this.hostnameVerifier != null) { - return CommonUtils.getResponseFromServer(validationUrl, this.hostnameVerifier, getEncoding()); - } else { - return CommonUtils.getResponseFromServer(validationUrl, getEncoding()); - } + return CommonUtils.getResponseFromServer(validationUrl, getURLConnectionFactory(), getEncoding()); } } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java index 00339b4..5edabb9 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java @@ -31,6 +31,8 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.FileInputStream; +import java.util.Properties; /** * The filter that handles all the work of validating ticket requests. @@ -81,6 +83,31 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter { return this.ticketValidator; } + /** + * Gets the ssl config to use for HTTPS connections + * if one is configured for this filter. + * @param filterConfig Servlet filter configuration. + * @return Properties that can contains key/trust info for Client Side Certificates + */ + protected Properties getSSLConfig(final FilterConfig filterConfig) { + final Properties properties = new Properties(); + final String fileName = getPropertyFromInitParams(filterConfig, "sslConfigFile", null); + + if (fileName != null) { + FileInputStream fis = null; + try { + fis = new FileInputStream(fileName); + properties.load(fis); + logger.trace("Loaded {} entries from {}", properties.size(), fileName); + } catch(final IOException ioe) { + logger.error(ioe.getMessage(), ioe); + } finally { + CommonUtils.closeQuietly(fis); + } + } + return properties; + } + /** * Gets the configured {@link HostnameVerifier} to use for HTTPS connections * if one is configured for this filter. diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractUrlBasedTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractUrlBasedTicketValidator.java index 5606ac5..5410669 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractUrlBasedTicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractUrlBasedTicketValidator.java @@ -18,6 +18,8 @@ */ package org.jasig.cas.client.validation; +import org.jasig.cas.client.ssl.HttpsURLConnectionFactory; +import org.jasig.cas.client.ssl.HttpURLConnectionFactory; import org.jasig.cas.client.util.CommonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,24 +31,22 @@ import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; -import javax.net.ssl.HostnameVerifier; - /** * Abstract validator implementation for tickets that must be validated against a server. * * @author Scott Battaglia - * @version $Revision$ $Date$ * @since 3.1 */ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator { protected final Logger logger = LoggerFactory.getLogger(getClass()); - + /** - * Hostname verifier used when making an SSL request to the CAS server. + * URLConnection factory instance to use when making validation requests to the CAS server. + * Defaults to {@link HttpsURLConnectionFactory} */ - protected HostnameVerifier hostnameVerifier; - + private HttpURLConnectionFactory urlConnectionFactory = new HttpsURLConnectionFactory(); + /** * Prefix for the CAS server. Should be everything up to the url endpoint, including the /. * @@ -217,10 +217,6 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator public final void setCustomParameters(final Map
Deployers can provide the "casServerPrefix" and the "renew" attributes via the standard context or filter init @@ -35,7 +38,9 @@ public class Cas10TicketValidationFilter extends AbstractTicketValidationFilter final String casServerUrlPrefix = getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", null); final Cas10TicketValidator validator = new Cas10TicketValidator(casServerUrlPrefix); validator.setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false"))); - validator.setHostnameVerifier(getHostnameVerifier(filterConfig)); + + final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(filterConfig), getSSLConfig(filterConfig)); + validator.setURLConnectionFactory(factory); validator.setEncoding(getPropertyFromInitParams(filterConfig, "encoding", null)); return validator; diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java index 5d31060..48935c5 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java @@ -30,6 +30,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jasig.cas.client.proxy.*; +import org.jasig.cas.client.ssl.HttpsURLConnectionFactory; +import org.jasig.cas.client.ssl.HttpURLConnectionFactory; import org.jasig.cas.client.util.CommonUtils; import org.jasig.cas.client.util.ReflectUtils; @@ -143,7 +145,11 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal } validator.setProxyCallbackUrl(getPropertyFromInitParams(filterConfig, "proxyCallbackUrl", null)); validator.setProxyGrantingTicketStorage(this.proxyGrantingTicketStorage); - validator.setProxyRetriever(new Cas20ProxyRetriever(casServerUrlPrefix, getPropertyFromInitParams(filterConfig, "encoding", null))); + + final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(filterConfig), getSSLConfig(filterConfig)); + validator.setURLConnectionFactory(factory); + + validator.setProxyRetriever(new Cas20ProxyRetriever(casServerUrlPrefix, getPropertyFromInitParams(filterConfig, "encoding", null), factory)); validator.setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false"))); validator.setEncoding(getPropertyFromInitParams(filterConfig, "encoding", null)); @@ -159,8 +165,6 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal } validator.setCustomParameters(additionalParameters); - validator.setHostnameVerifier(getHostnameVerifier(filterConfig)); - return validator; } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java index c626d6d..9c90eaf 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java @@ -25,7 +25,6 @@ import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; import org.jasig.cas.client.proxy.ProxyRetriever; import org.jasig.cas.client.util.CommonUtils; import org.jasig.cas.client.util.XmlUtils; -import org.w3c.dom.NodeList; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -41,7 +40,6 @@ import java.util.*; * Implementation of the TicketValidator that will validate Service Tickets in compliance with the CAS 2. * * @author Scott Battaglia - * @version $Revision$ $Date$ * @since 3.1 */ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTicketValidator { @@ -60,10 +58,11 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick * CAS server url prefix. * * @param casServerUrlPrefix the CAS Server URL prefix. + * @param urlFactory URL connection factory to use when communicating with the server */ public Cas20ServiceTicketValidator(final String casServerUrlPrefix) { super(casServerUrlPrefix); - this.proxyRetriever = new Cas20ProxyRetriever(casServerUrlPrefix, getEncoding()); + this.proxyRetriever = new Cas20ProxyRetriever(casServerUrlPrefix, getEncoding(), getURLConnectionFactory()); } /** diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidationFilter.java index 8ac6e52..e35bf83 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidationFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidationFilter.java @@ -21,6 +21,9 @@ package org.jasig.cas.client.validation; import javax.servlet.FilterConfig; import javax.servlet.ServletException; +import org.jasig.cas.client.ssl.HttpsURLConnectionFactory; +import org.jasig.cas.client.ssl.HttpURLConnectionFactory; + /** * Implementation of TicketValidationFilter that can instanciate a SAML 1.1 Ticket Validator. *
@@ -53,7 +56,10 @@ public class Saml11TicketValidationFilter extends AbstractTicketValidationFilter
final String tolerance = getPropertyFromInitParams(filterConfig, "tolerance", "1000");
validator.setTolerance(Long.parseLong(tolerance));
validator.setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
- validator.setHostnameVerifier(getHostnameVerifier(filterConfig));
+
+ final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(filterConfig), getSSLConfig(filterConfig));
+ validator.setURLConnectionFactory(factory);
+
validator.setEncoding(getPropertyFromInitParams(filterConfig, "encoding", null));
validator.setDisableXmlSchemaValidation(parseBoolean(getPropertyFromInitParams(filterConfig, "disableXmlSchemaValidation", "false")));
return validator;
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidator.java
index 8a1d775..6f467d8 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidator.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidator.java
@@ -36,6 +36,7 @@ import org.opensaml.xml.io.UnmarshallingException;
import org.opensaml.xml.parse.BasicParserPool;
import org.opensaml.xml.parse.XMLParserException;
import org.opensaml.xml.schema.XSAny;
+import org.opensaml.xml.schema.XSString;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -45,13 +46,10 @@ import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;
-import javax.net.ssl.HttpsURLConnection;
-
/**
* TicketValidator that can understand validating a SAML artifact. This includes the SOAP request/response.
*
* @author Scott Battaglia
- * @version $Revision$ $Date$
* @since 3.1
*/
public final class Saml11TicketValidator extends AbstractUrlBasedTicketValidator {
@@ -220,6 +218,8 @@ public final class Saml11TicketValidator extends AbstractUrlBasedTicketValidator
for (final Object o : attribute.getAttributeValues()) {
if (o instanceof XSAny) {
list.add(((XSAny) o).getTextContent());
+ } else if (o instanceof XSString) {
+ list.add(((XSString) o).getValue());
} else {
list.add(o.toString());
}
@@ -232,12 +232,11 @@ public final class Saml11TicketValidator extends AbstractUrlBasedTicketValidator
+ "