[SIDP-229] - IdP Metadata changes to KeyDescriptor not fully flushed from IdP cache
[SIDP-230] - sanity check provided credentials
[SIDP-233] - Typo on operation name - public void setAuthenticationDurection(long duration)
-[SIDP-237] - Re-run of install.sh does not create war again
\ No newline at end of file
+[SIDP-237] - Re-run of install.sh does not create war again
+[SIDP-242] - Cleanup StorageService entry classes
\ No newline at end of file
<tc:tc-config xmlns:tc="http://www.terracotta.org/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.terracotta.org/config http://www.terracotta.org/schema/terracotta-4.xsd">
-
+
<!--
Terracotta configuration file for Shibboleth.
-
+
Complete documentation on the contents of this file may be found here:
http://terracotta.org/web/display/docs/Configuration+Guide+and+Reference
-->
-
+
<servers>
<!-- EXAMPLE SERVER CONFIGURATION -->
- <!--
- <server name="UNIQUE_ID" host="HOST">
+ <!--
+ <server name="UNIQUE_ID" host="HOST">
<dso>
- <persistence>
- <mode>permanent-store</mode>
- </persistence>
+ <persistence>
+ <mode>permanent-store</mode>
+ </persistence>
</dso>
<logs>$IDP_HOME$/cluster/server/logs</logs>
<data>$IDP_HOME$/cluster/server/data</data>
<statistics>$IDP_HOME$/cluster/server/stats</statistics>
- </server>
+ </server>
-->
<!-- START Terracotta server definitions -->
<!-- END Terracotta server definitions -->
-
+
<ha>
<mode>networked-active-passive</mode>
<networked-active-passive>
</networked-active-passive>
</ha>
</servers>
-
+
<system>
<configuration-model>production</configuration-model>
</system>
-
+
<clients>
<logs>$IDP_HOME$/cluster/client/logs-%i</logs>
<statistics>$IDP_HOME$/cluster/client/stats-%i</statistics>
</clients>
-
+
<application>
<dso>
+ <additional-boot-jar-classes>
+ <include>javax.security.auth.Subject</include>
+ <include>javax.security.auth.Subject$SecureSet</include>
+ <include>javax.security.auth.x500.X500Principal</include>
+ <include>javax.security.auth.kerberos.KerberosPrincipal</include>
+ </additional-boot-jar-classes>
<roots>
<root>
<root-name>storageService</root-name>
<field-name>edu.internet2.middleware.shibboleth.common.util.EventingMapBasedStorageService.store</field-name>
</root>
</roots>
+ <instrumented-classes>
+ <include>
+ <class-expression>edu.vt.middleware.ldap.jaas.LdapPrincipal</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.vt.middleware.ldap.jaas.LdapCredential</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.idp.authn.AuthenticationException</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>org.opensaml.util.storage.AbstractExpiringObject</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.attributeDefinition.IdEntry</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.idp.authn.LoginContextEntry</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.idp.authn.LoginContext</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.idp.authn.ShibbolethSSOLoginContext</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.idp.authn.Saml2LoginContext</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>org.opensaml.util.storage.ReplayCacheEntry</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.idp.session.impl.SessionManagerEntry</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.common.session.impl.AbstractSession</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.idp.session.impl.SessionImpl</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>edu.internet2.middleware.shibboleth.idp.session.impl.ServiceInformationImpl</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ <include>
+ <class-expression>org.opensaml.common.binding.artifact.BasicSAMLArtifactMapEntry</class-expression>
+ <honor-transient>true</honor-transient>
+ </include>
+ </instrumented-classes>
+ <locks>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.vt.middleware.ldap.jaas.LdapPrincipal.*(..)</method-expression>
+ <lock-level>write</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.authn.LoginContext.set*(..)</method-expression>
+ <lock-level>write</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.authn.LoginContext.get*(..)</method-expression>
+ <lock-level>read</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.authn.ShibbolethSSOLoginContext.set*(..)</method-expression>
+ <lock-level>write</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.authn.ShibbolethSSOLoginContext.get*(..)</method-expression>
+ <lock-level>read</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.authn.Saml2LoginContext.set*(..)</method-expression>
+ <lock-level>write</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.authn.Saml2LoginContext.get*(..)</method-expression>
+ <lock-level>read</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.common.session.impl.AbstractSession.set*(..)</method-expression>
+ <lock-level>write</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.common.session.impl.AbstractSession.get*(..)</method-expression>
+ <lock-level>read</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.session.impl.SessionImpl.set*(..)</method-expression>
+ <lock-level>write</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.session.impl.SessionImpl.get*(..)</method-expression>
+ <lock-level>read</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl.set*(..)</method-expression>
+ <lock-level>write</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.session.impl.AuthenticationMethodInformationImpl.get*(..)</method-expression>
+ <lock-level>read</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.session.impl.ServiceInformationImpl.set*(..)</method-expression>
+ <lock-level>write</lock-level>
+ </autolock>
+ <autolock auto-synchronized="false">
+ <method-expression>* edu.internet2.middleware.shibboleth.idp.session.impl.ServiceInformationImpl.get*(..)</method-expression>
+ <lock-level>read</lock-level>
+ </autolock>
+ </locks>
</dso>
</application>
-
+
</tc:tc-config>
\ No newline at end of file
import java.io.IOException;
import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Set;
import java.util.Map.Entry;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
import javax.security.auth.Subject;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import org.opensaml.common.IdentifierGenerator;
import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
import org.opensaml.saml2.core.AuthnContext;
-import org.opensaml.util.storage.ExpiringObject;
import org.opensaml.util.storage.StorageService;
import org.opensaml.ws.transport.http.HTTPTransportUtils;
import org.opensaml.xml.util.Base64;
*/
protected void validateSuccessfulAuthentication(LoginContext loginContext, HttpServletRequest httpRequest)
throws AuthenticationException {
+ LOG.debug("Validating authentication was performed successfully");
+
String errorMessage = DatatypeHelper.safeTrimOrNullString((String) httpRequest
.getAttribute(LoginHandler.AUTHENTICATION_ERROR_KEY));
if (errorMessage != null) {
*/
protected void updateUserSession(LoginContext loginContext, Subject authenticationSubject,
String authenticationMethod, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
-
Principal authenticationPrincipal = authenticationSubject.getPrincipals().iterator().next();
+ LOG.debug("Updating session information for principal {}", authenticationPrincipal.getName());
Session idpSession = (Session) httpRequest.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
if (idpSession == null) {
byte[] sessionId = userSession.getSessionID().getBytes();
String signature = null;
- SecretKey signingKey = userSession.getSessionSecretKey();
try {
- Mac mac = Mac.getInstance("HmacSHA256");
- mac.init(signingKey);
- mac.update(remoteAddress);
- mac.update(sessionId);
- signature = Base64.encodeBytes(mac.doFinal());
+ MessageDigest digester = MessageDigest.getInstance("SHA");
+ digester.update(userSession.getSessionSecret());
+ digester.update(remoteAddress);
+ digester.update(sessionId);
+ signature = Base64.encodeBytes(digester.digest());
} catch (GeneralSecurityException e) {
LOG.error("Unable to compute signature over session cookie material", e);
}
httpResponse.addCookie(sessionCookie);
}
-
- /** Storage service entry for login contexts. */
- public class LoginContextEntry implements ExpiringObject {
-
- /** Stored login context. */
- private LoginContext loginCtx;
-
- /** Time the entry expires. */
- private DateTime expirationTime;
-
- /**
- * Constructor.
- *
- * @param ctx context to store
- * @param lifetime lifetime of the entry
- */
- public LoginContextEntry(LoginContext ctx, long lifetime) {
- loginCtx = ctx;
- expirationTime = new DateTime().plus(lifetime);
- }
-
- /**
- * Gets the login context.
- *
- * @return login context
- */
- public LoginContext getLoginContext() {
- return loginCtx;
- }
-
- /** {@inheritDoc} */
- public DateTime getExpirationTime() {
- return expirationTime;
- }
-
- /** {@inheritDoc} */
- public boolean isExpired() {
- return expirationTime.isBeforeNow();
- }
-
- /** {@inheritDoc} */
- public void onExpire() {
-
- }
- }
}
\ No newline at end of file
*
* The {@link AuthenticationEngine} should set the {@link LoginContext#setAuthenticationAttempted()},
* {@link LoginContext#setPrincipalAuthenticated(boolean)},
- * {@link LoginContext#setAuthenticationFailure(AuthenticationException)},
- *
- * appropriately.
+ * {@link LoginContext#setAuthenticationFailure(AuthenticationException)}, appropriately.
*/
public class LoginContext implements Serializable {
*
* @return authentication method that was used when attempting to authenticate the user
*/
- public String getAttemptedAuthnMethod() {
+ public synchronized String getAttemptedAuthnMethod() {
return attemptedAuthnMethod;
}
*
* @return if authentication has been attempted for this user
*/
- public boolean getAuthenticationAttempted() {
+ public synchronized boolean getAuthenticationAttempted() {
return authnAttempted;
}
*
* @return The duration of authentication, or zero if none was set.
*/
- public long getAuthenticationDuration() {
+ public synchronized long getAuthenticationDuration() {
return authenticationMethodInformation.getAuthenticationDuration();
}
*
* @return the URL of the authentication engine
*/
- public String getAuthenticationEngineURL() {
+ public synchronized String getAuthenticationEngineURL() {
return authnEngineURL;
}
*
* @return error that occurred during authentication
*/
- public AuthenticationException getAuthenticationFailure() {
+ public synchronized AuthenticationException getAuthenticationFailure() {
return authnException;
}
*
* @return The instant of authentication, or <code>null</code> if none was set.
*/
- public DateTime getAuthenticationInstant() {
+ public synchronized DateTime getAuthenticationInstant() {
return authenticationMethodInformation.getAuthenticationInstant();
}
*
* @return The method used to authenticate the user.
*/
- public String getAuthenticationMethod() {
+ public synchronized String getAuthenticationMethod() {
return authenticationMethodInformation.getAuthenticationMethod();
}
*
* @return information about the authentication event.
*/
- public AuthenticationMethodInformation getAuthenticationMethodInformation() {
+ public synchronized AuthenticationMethodInformation getAuthenticationMethodInformation() {
return authenticationMethodInformation;
}
*
* @return the ID of the user, or <code>null</code> if authentication failed.
*/
- public String getPrincipalName() {
+ public synchronized String getPrincipalName() {
return authenticationMethodInformation.getAuthenticationPrincipal().getName();
}
*
* @return the URL of the profile handler that is invoking the Authentication Manager.
*/
- public String getProfileHandlerURL() {
+ public synchronized String getProfileHandlerURL() {
return profileHandlerURL;
}
*
* @return The object, or <code>null</code> is no object exists for the key.
*/
- public Object getProperty(String key) {
+ public synchronized Object getProperty(String key) {
return propsMap.get(key);
}
*
* @return entity ID of the relying party
*/
- public String getRelyingPartyId() {
+ public synchronized String getRelyingPartyId() {
return relyingPartyId;
}
*
* @return an list of authentication method identifiers
*/
- public List<String> getRequestedAuthenticationMethods() {
+ public synchronized List<String> getRequestedAuthenticationMethods() {
return requestAuthenticationMethods;
}
*
* @return the Session id
*/
- public String getSessionID() {
+ public synchronized String getSessionID() {
return sessionID;
}
*
* @return <code>true</code> if the authentication manager must re-authenticate the user.
*/
- public boolean isForceAuthRequired() {
+ public synchronized boolean isForceAuthRequired() {
return forceAuth;
}
*
* @return <code>true</code> if the authentication manager must not interact with the users UI.
*/
- public boolean isPassiveAuthRequired() {
+ public synchronized boolean isPassiveAuthRequired() {
return passiveAuth;
}
*
* @return <code>true</code> is the user was successfully authenticated.
*/
- public boolean isPrincipalAuthenticated() {
+ public synchronized boolean isPrincipalAuthenticated() {
return principalAuthenticated;
}
*
* @param method authentication method that was used when attempting to authenticate the user
*/
- public void setAttemptedAuthnMethod(String method) {
+ public synchronized void setAttemptedAuthnMethod(String method) {
attemptedAuthnMethod = method;
}
*
* This method should be called by an {@link LoginHandler} while processing a request.
*/
- public void setAuthenticationAttempted() {
+ public synchronized void setAuthenticationAttempted() {
authnAttempted = true;
}
*
* @deprecated this information is contained in the {@link AuthenticationMethodInformation}
*/
- public void setAuthenticationDuration(long duration) {
+ public synchronized void setAuthenticationDuration(long duration) {
}
/**
*
* @param url the URL of the authentication engine
*/
- public void setAuthenticationEngineURL(String url) {
+ public synchronized void setAuthenticationEngineURL(String url) {
authnEngineURL = url;
}
*
* @param error error that occurred during authentication
*/
- public void setAuthenticationFailure(AuthenticationException error) {
+ public synchronized void setAuthenticationFailure(AuthenticationException error) {
authnException = error;
}
*
* @deprecated this information is contained in the {@link AuthenticationMethodInformation}
*/
- public void setAuthenticationInstant(final DateTime instant) {
+ public synchronized void setAuthenticationInstant(final DateTime instant) {
}
/**
*
* @deprecated this information is contained in the {@link AuthenticationMethodInformation}
*/
- public void setAuthenticationMethod(String method) {
+ public synchronized void setAuthenticationMethod(String method) {
}
/**
*
* @param info information about the authentication event
*/
- public void setAuthenticationMethodInformation(AuthenticationMethodInformation info) {
+ public synchronized void setAuthenticationMethodInformation(AuthenticationMethodInformation info) {
authenticationMethodInformation = info;
}
*
* @param force if the authentication manager must re-authenticate the user.
*/
- public void setForceAuthRequired(boolean force) {
+ public synchronized void setForceAuthRequired(boolean force) {
forceAuth = force;
}
*
* @param passive if the authentication manager must not interact with the users UI.
*/
- public void setPassiveAuthRequired(boolean passive) {
+ public synchronized void setPassiveAuthRequired(boolean passive) {
passiveAuth = passive;
}
*
* @param authnOK if authentication succeeded;
*/
- public void setPrincipalAuthenticated(boolean authnOK) {
+ public synchronized void setPrincipalAuthenticated(boolean authnOK) {
this.principalAuthenticated = authnOK;
}
*
* @deprecated this information is contained in the {@link AuthenticationMethodInformation}
*/
- public void setPrincipalName(String id) {
+ public synchronized void setPrincipalName(String id) {
}
*
* @param url The URL of the profile handler that invoked the AuthenticationManager/
*/
- public void setProfileHandlerURL(String url) {
+ public synchronized void setProfileHandlerURL(String url) {
profileHandlerURL = url;
}
* @param key The key to set.
* @param obj The object to associate with key.
*/
- public void setProperty(String key, final Serializable obj) {
+ public synchronized void setProperty(String key, final Serializable obj) {
propsMap.put(key, obj);
}
*
* @param id entity ID of the relying party
*/
- public void setRelyingParty(String id) {
+ public synchronized void setRelyingParty(String id) {
relyingPartyId = id;
}
*
* @param id the Session ID
*/
- public void setSessionID(String id) {
+ public synchronized void setSessionID(String id) {
sessionID = id;
}
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2008 University Corporation for Advanced Internet Development, Inc.
+ *
+ * Licensed 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
+ *
+ * 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 edu.internet2.middleware.shibboleth.idp.authn;
+
+import org.joda.time.DateTime;
+import org.opensaml.util.storage.AbstractExpiringObject;
+
+/** Storage service entry for login contexts. */
+public class LoginContextEntry extends AbstractExpiringObject {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = -1528197153404835381L;
+
+ /** Stored login context. */
+ private LoginContext loginCtx;
+
+ /**
+ * Constructor.
+ *
+ * @param ctx context to store
+ * @param lifetime lifetime of the entry
+ */
+ public LoginContextEntry(LoginContext ctx, long lifetime) {
+ super(new DateTime().plus(lifetime));
+ loginCtx = ctx;
+ }
+
+ /**
+ * Gets the login context.
+ *
+ * @return login context
+ */
+ public LoginContext getLoginContext() {
+ return loginCtx;
+ }
+}
\ No newline at end of file
*
* @throws UnmarshallingException thrown if the serialized form on the authentication request can be unmarshalled
*/
- public AuthnRequest getAuthenticationRequest() throws UnmarshallingException {
+ public synchronized AuthnRequest getAuthenticationRequest() throws UnmarshallingException {
if (authnRequest == null) {
authnRequest = deserializeRequest(serialAuthnRequest);
}
}
/**
- * Gets the relay state from the orginating authentication request.
+ * Gets the relay state from the originating authentication request.
*
- * @return relay state from the orginating authentication request
+ * @return relay state from the originating authentication request
*/
- public String getRelayState(){
+ public synchronized String getRelayState(){
return relayState;
}
*
* @return requested authentication context information or null
*/
- public RequestedAuthnContext getRequestedAuthenticationContext() {
+ public synchronized RequestedAuthnContext getRequestedAuthenticationContext() {
try {
AuthnRequest request = getAuthenticationRequest();
return request.getRequestedAuthnContext();
*
* @return service provider assertion consumer service URL
*/
- public String getSpAssertionConsumerService() {
+ public synchronized String getSpAssertionConsumerService() {
return spAssertionConsumerService;
}
*
* @param url service provider assertion consumer service URL
*/
- public void setSpAssertionConsumerService(String url) {
+ public synchronized void setSpAssertionConsumerService(String url) {
spAssertionConsumerService = url;
}
*
* @return service provider target URL
*/
- public String getSpTarget() {
+ public synchronized String getSpTarget() {
return spTarget;
}
*
* @param url service provider target URL
*/
- public void setSpTarget(String url) {
+ public synchronized void setSpTarget(String url) {
spTarget = url;
}
}
\ No newline at end of file
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.common.binding.BasicEndpointSelector;
import org.opensaml.common.binding.artifact.SAMLArtifactMap;
-import org.opensaml.common.binding.artifact.SAMLArtifactMap.SAMLArtifactMapEntry;
+import org.opensaml.common.binding.artifact.SAMLArtifactMapEntry;
import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml1.binding.SAML1ArtifactMessageContext;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.common.binding.BasicEndpointSelector;
import org.opensaml.common.binding.artifact.SAMLArtifactMap;
-import org.opensaml.common.binding.artifact.SAMLArtifactMap.SAMLArtifactMapEntry;
+import org.opensaml.common.binding.artifact.SAMLArtifactMapEntry;
import org.opensaml.common.binding.decoding.SAMLMessageDecoder;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.binding.SAML2ArtifactMessageContext;
package edu.internet2.middleware.shibboleth.idp.session;
+import java.io.Serializable;
import java.security.Principal;
import javax.security.auth.Subject;
import org.joda.time.DateTime;
/** Information about an authentication method employed by a user. */
-public interface AuthenticationMethodInformation {
+public interface AuthenticationMethodInformation extends Serializable {
/**
* Gets the Subject created by this authentication method.
import java.io.IOException;
import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
import java.util.Arrays;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
Session userSession = sessionManager.getSession(sessionId);
if (userSession != null) {
- SecretKey signingKey = userSession.getSessionSecretKey();
try {
- Mac mac = Mac.getInstance("HmacSHA256");
- mac.init(signingKey);
- mac.update(remoteAddressBytes);
- mac.update(sessionIdBytes);
- byte[] signature = mac.doFinal();
-
- if (!Arrays.equals(signature, signatureBytes)) {
+ MessageDigest digester = MessageDigest.getInstance("SHA");
+ digester.update(userSession.getSessionSecret());
+ digester.update(remoteAddressBytes);
+ digester.update(sessionIdBytes);
+ if (!Arrays.equals(digester.digest(), signatureBytes)) {
log.error("Session cookie signature did not match, the session cookie has been tampered with");
return null;
}
package edu.internet2.middleware.shibboleth.idp.session;
+import java.io.Serializable;
+
import org.joda.time.DateTime;
/** Information about a service a user has logged in to. */
-public interface ServiceInformation {
+public interface ServiceInformation extends Serializable {
/**
* Gets the unique identifier for the service.
import java.util.Map;
-import javax.crypto.SecretKey;
-
/**
* Session information for user logged into the IdP.
*/
/** Name of the HTTP request attribute to which a users IdP session is bound. */
public static final String HTTP_SESSION_BINDING_ATTRIBUTE = "ShibbolethIdPSession";
-
+
/**
- * A secret key associated with this session.
+ * A secret associated with this session.
*
- * @return secret key associated with this session
+ * @return secret associated with this session
*/
- public SecretKey getSessionSecretKey();
+ public byte[] getSessionSecret();
/**
* Gets the methods by which the user has authenticated to the IdP.
import javax.security.auth.Subject;
import org.joda.time.DateTime;
+import org.joda.time.chrono.ISOChronology;
import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
-/**
- * Information about an authentication method employed by a user.
- */
+/** Information about an authentication method employed by a user. */
public class AuthenticationMethodInformationImpl implements AuthenticationMethodInformation {
+ /** Serial version UID. */
+ private static final long serialVersionUID = -2108905664641155003L;
+
/** Subject created by this authentication mechanism. */
private Subject authenticationSubject;
private String authenticationMethod;
/** The timestamp at which authentication occurred. */
- private DateTime authenticationInstant;
+ private long authenticationInstant;
/** The lifetime of the authentication method. */
private long authenticationDuration;
/** Time when this method expires. */
- private DateTime expirationInstant;
+ private long expirationInstant;
/**
* Default constructor. This constructor does NOT add the given principal to the given subject.
authenticationSubject = subject;
authenticationPrincipal = principal;
authenticationMethod = method;
- authenticationInstant = instant;
+ authenticationInstant = instant.toDateTime(ISOChronology.getInstanceUTC()).getMillis();
authenticationDuration = duration;
- expirationInstant = instant.plus(duration);
+ expirationInstant = authenticationInstant + duration;
}
/** {@inheritDoc} */
- public Subject getAuthenticationSubject() {
+ public synchronized Subject getAuthenticationSubject() {
return authenticationSubject;
}
/** {@inheritDoc} */
- public Principal getAuthenticationPrincipal() {
+ public synchronized Principal getAuthenticationPrincipal() {
return authenticationPrincipal;
}
/** {@inheritDoc} */
- public String getAuthenticationMethod() {
+ public synchronized String getAuthenticationMethod() {
return authenticationMethod;
}
/** {@inheritDoc} */
- public DateTime getAuthenticationInstant() {
- return authenticationInstant;
+ public synchronized DateTime getAuthenticationInstant() {
+ return new DateTime(authenticationInstant, ISOChronology.getInstanceUTC());
}
/** {@inheritDoc} */
- public long getAuthenticationDuration() {
+ public synchronized long getAuthenticationDuration() {
return authenticationDuration;
}
/** {@inheritDoc} */
- public boolean isExpired() {
- return expirationInstant.isBeforeNow();
+ public synchronized boolean isExpired() {
+ return new DateTime(expirationInstant, ISOChronology.getInstanceUTC()).isBeforeNow();
}
/** {@inheritDoc} */
- public int hashCode() {
+ public synchronized int hashCode() {
return authenticationMethod.hashCode();
}
/** {@inheritDoc} */
- public boolean equals(Object obj) {
+ public synchronized boolean equals(Object obj) {
if (obj == this) {
return true;
}
package edu.internet2.middleware.shibboleth.idp.session.impl;
import org.joda.time.DateTime;
+import org.joda.time.chrono.ISOChronology;
import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
import edu.internet2.middleware.shibboleth.idp.session.ServiceInformation;
/** Information about a service a user has logged in to. */
public class ServiceInformationImpl implements ServiceInformation {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = 1185342879825302743L;
/** Entity ID of the service. */
private String entityID;
/** Instant the user was authenticated to the service. */
- private DateTime authenticationInstant;
+ private long authenticationInstant;
/** Authentication method used to authenticate the user to the service. */
private AuthenticationMethodInformation methodInfo;
*/
public ServiceInformationImpl(String id, DateTime loginInstant, AuthenticationMethodInformation method) {
entityID = id;
- authenticationInstant = loginInstant;
+ authenticationInstant = loginInstant.toDateTime(ISOChronology.getInstanceUTC()).getMillis();
methodInfo = method;
}
/** {@inheritDoc} */
- public String getEntityID() {
+ public synchronized String getEntityID() {
return entityID;
}
/** {@inheritDoc} */
- public DateTime getLoginInstant() {
- return authenticationInstant;
+ public synchronized DateTime getLoginInstant() {
+ return new DateTime(authenticationInstant, ISOChronology.getInstanceUTC());
}
/** {@inheritDoc} */
- public AuthenticationMethodInformation getAuthenticationMethod() {
+ public synchronized AuthenticationMethodInformation getAuthenticationMethod() {
return methodInfo;
}
/** {@inheritDoc} */
- public int hashCode() {
+ public synchronized int hashCode() {
return entityID.hashCode();
}
/** {@inheritDoc} */
- public boolean equals(Object obj) {
+ public synchronized boolean equals(Object obj) {
if (obj == this) {
return true;
}
package edu.internet2.middleware.shibboleth.idp.session.impl;
-import java.util.HashMap;
import java.util.Map;
-
-import javax.crypto.SecretKey;
+import java.util.concurrent.ConcurrentHashMap;
import edu.internet2.middleware.shibboleth.common.session.impl.AbstractSession;
import edu.internet2.middleware.shibboleth.idp.session.AuthenticationMethodInformation;
/** Serial version UID. */
private static final long serialVersionUID = 2927868242208211623L;
-
+
/** Secret key associated with the session. */
- private SecretKey sessionKey;
+ private byte[] sessionSecret;
/** The list of methods used to authenticate the user. */
- private HashMap<String, AuthenticationMethodInformation> authnMethods;
+ private Map<String, AuthenticationMethodInformation> authnMethods;
/** The list of services to which the user has logged in. */
- private HashMap<String, ServiceInformation> servicesInformation;
+ private Map<String, ServiceInformation> servicesInformation;
/**
* Constructor.
*
* @param sessionId ID of the session
- * @param key a secret key to associate with the session
+ * @param secret a secret to associate with the session
* @param timeout inactivity timeout for the session in milliseconds
*/
- public SessionImpl(String sessionId, SecretKey key, long timeout) {
+ public SessionImpl(String sessionId, byte[] secret, long timeout) {
super(sessionId, timeout);
- sessionKey = key;
-
- authnMethods = new HashMap<String, AuthenticationMethodInformation>();
- servicesInformation = new HashMap<String, ServiceInformation>();
+ sessionSecret = secret;
+ authnMethods = new ConcurrentHashMap<String, AuthenticationMethodInformation>();
+ servicesInformation = new ConcurrentHashMap<String, ServiceInformation>();
}
-
+
/** {@inheritDoc} */
- public SecretKey getSessionSecretKey() {
- return sessionKey;
+ public synchronized byte[] getSessionSecret() {
+ return sessionSecret;
}
/** {@inheritDoc} */
- public Map<String, AuthenticationMethodInformation> getAuthenticationMethods() {
+ public synchronized Map<String, AuthenticationMethodInformation> getAuthenticationMethods() {
return authnMethods;
}
/** {@inheritDoc} */
- public Map<String, ServiceInformation> getServicesInformation() {
+ public synchronized Map<String, ServiceInformation> getServicesInformation() {
return servicesInformation;
}
*
* @return the service information or null
*/
- public ServiceInformation getServiceInformation(String entityId) {
+ public synchronized ServiceInformation getServiceInformation(String entityId) {
return servicesInformation.get(entityId);
}
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2008 University Corporation for Advanced Internet Development, Inc.
+ *
+ * Licensed 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
+ *
+ * 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.
+ */
+
+/*
+ * Copyright 2008 University Corporation for Advanced Internet Development, Inc.
+ *
+ * Licensed 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
+ *
+ * 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 edu.internet2.middleware.shibboleth.idp.session.impl;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.joda.time.DateTime;
+import org.opensaml.util.storage.AbstractExpiringObject;
+
+import edu.internet2.middleware.shibboleth.idp.session.Session;
+
+/** Session store entry. */
+public class SessionManagerEntry extends AbstractExpiringObject {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = -9160494097986587739L;
+
+ /** User's session. */
+ private Session userSession;
+
+ /** Indexes for this session. */
+ private List<String> indexes;
+
+ /**
+ * Constructor.
+ *
+ * @param session user session
+ * @param lifetime lifetime of session
+ */
+ public SessionManagerEntry(Session session, long lifetime) {
+ super(new DateTime().plus(lifetime));
+ userSession = session;
+ indexes = new Vector<String>();
+ indexes.add(userSession.getSessionID());
+ }
+
+ /**
+ * Gets the user session.
+ *
+ * @return user session
+ */
+ public Session getSession() {
+ return userSession;
+ }
+
+ /**
+ * Gets the ID of the user session.
+ *
+ * @return ID of the user session
+ */
+ public String getSessionId() {
+ return userSession.getSessionID();
+ }
+
+ /**
+ * Gets the list of indexes for this session.
+ *
+ * @return list of indexes for this session
+ */
+ public List<String> getSessionIndexes() {
+ return indexes;
+ }
+}
\ No newline at end of file
package edu.internet2.middleware.shibboleth.idp.session.impl;
-import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
-import java.util.List;
-import java.util.Vector;
-
-import javax.crypto.KeyGenerator;
import org.apache.commons.ssl.util.Hex;
-import org.joda.time.DateTime;
-import org.opensaml.util.storage.ExpiringObject;
import org.opensaml.util.storage.StorageService;
import org.opensaml.xml.util.DatatypeHelper;
import org.slf4j.Logger;
/** Spring context used to publish login and logout events. */
private ApplicationContext appCtx;
- /** Generator used to create secret keys associated with the session. */
- private KeyGenerator secretKeyGen;
-
/** Number of random bits within a session ID. */
private final int sessionIDSize = 32;
sessionStore = storageService;
partition = "session";
sessionLifetime = lifetime;
-
- try {
- secretKeyGen = KeyGenerator.getInstance("AES");
- } catch (NoSuchAlgorithmException e) {
- log.error("AES key generation is not supported", e);
- }
}
/**
byte[] sid = new byte[sessionIDSize];
prng.nextBytes(sid);
String sessionID = Hex.encode(sid);
+
+ byte[] sessionSecret = new byte[16];
+ prng.nextBytes(sessionSecret);
- Session session = new SessionImpl(sessionID, secretKeyGen.generateKey(), sessionLifetime);
+ Session session = new SessionImpl(sessionID, sessionSecret, sessionLifetime);
SessionManagerEntry sessionEntry = new SessionManagerEntry(session, sessionLifetime);
sessionStore.put(partition, sessionID, sessionEntry);
byte[] sid = new byte[sessionIDSize];
prng.nextBytes(sid);
String sessionID = Hex.encode(sid);
+
+ byte[] sessionSecret = new byte[16];
+ prng.nextBytes(sessionSecret);
- MDC.put("idpSessionId", sessionID);
-
- Session session = new SessionImpl(sessionID, secretKeyGen.generateKey(), sessionLifetime);
+ Session session = new SessionImpl(sessionID, sessionSecret, sessionLifetime);
SessionManagerEntry sessionEntry = new SessionManagerEntry(session, sessionLifetime);
sessionStore.put(partition, sessionID, sessionEntry);
+
+ MDC.put("idpSessionId", sessionID);
log.trace("Created session {}", sessionID);
return session;
}
}
appCtx = rootContext;
}
-
- /** Session store entry. */
- public class SessionManagerEntry implements ExpiringObject {
-
- /** User's session. */
- private Session userSession;
-
- /** Indexes for this session. */
- private List<String> indexes;
-
- /** Time this entry expires. */
- private DateTime expirationTime;
-
- /**
- * Constructor.
- *
- * @param session user session
- * @param lifetime lifetime of session
- */
- public SessionManagerEntry(Session session, long lifetime) {
- userSession = session;
- expirationTime = new DateTime().plus(lifetime);
- indexes = new Vector<String>();
- indexes.add(userSession.getSessionID());
- }
-
- /** {@inheritDoc} */
- public DateTime getExpirationTime() {
- return expirationTime;
- }
-
- /**
- * Gets the user session.
- *
- * @return user session
- */
- public Session getSession() {
- return userSession;
- }
-
- /**
- * Gets the ID of the user session.
- *
- * @return ID of the user session
- */
- public String getSessionId() {
- return userSession.getSessionID();
- }
-
- /**
- * Gets the list of indexes for this session.
- *
- * @return list of indexes for this session
- */
- public List<String> getSessionIndexes() {
- return indexes;
- }
-
- /** {@inheritDoc} */
- public boolean isExpired() {
- return expirationTime.isBeforeNow();
- }
-
- /** {@inheritDoc} */
- public void onExpire() {
-
- }
- }
}
\ No newline at end of file
import org.joda.time.DateTime;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.common.binding.artifact.SAMLArtifactMap;
-import org.opensaml.common.binding.artifact.SAMLArtifactMap.SAMLArtifactMapEntry;
+import org.opensaml.common.binding.artifact.SAMLArtifactMapEntry;
import org.opensaml.saml1.binding.artifact.SAML1ArtifactType0002;
import org.opensaml.saml1.core.Assertion;
import org.opensaml.saml1.core.AssertionArtifact;
import org.joda.time.DateTime;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.common.binding.artifact.SAMLArtifactMap;
-import org.opensaml.common.binding.artifact.SAMLArtifactMap.SAMLArtifactMapEntry;
+import org.opensaml.common.binding.artifact.SAMLArtifactMapEntry;
import org.opensaml.saml2.binding.artifact.SAML2ArtifactType0004;
import org.opensaml.saml2.core.Artifact;
import org.opensaml.saml2.core.ArtifactResolve;