Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,7 @@ partitionedCookie.desc=Specifies whether to partition SSO cookies with SameSite
partitionedCookieTrue=Always partition SSO cookies that have SameSite set to None.
partitionedCookieFalse=Do not partition SSO cookies.
partitionedCookieDefer=Allow the HTTP transport settings to determine whether to partition SSO cookies.

# The word JASPIC should not be translated
overrideHAMProcessing=Override the use of Http Authentication Mechanisms during JASPIC processing.
overrideHAMProcessing.desc=When set to true, overrides the use of any defined Http Authentication Mechanisms during JASPIC authentication processing, even if JASPIC is enabled. This applies to all applications. Defaults to false.
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,10 @@
<AD id="loggedOutCookieCacheService.cardinality.minimum" type="String" default="${count(loggedOutCookieCacheRef)}"
ibm:final="true" name="internal" description="internal use only"/>

</OCD>
<AD id="overrideHAMProcessing" name="%overrideHAMProcessing" description="%overrideHAMProcessing.desc" required="false"
type="Boolean" default="false"/>

</OCD>
<Designate pid="com.ibm.ws.webcontainer.security.WebAppSecurityCollaboratorImpl">
<Object ocdref="com.ibm.ws.webcontainer.security.metatype"/>
</Designate>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -242,18 +243,39 @@ public synchronized void unsetInterceptorService(ServiceReference<TrustAssociati
interceptorServiceRef.removeReference(id, ref);
}

private void outputStackTraceToDebug() {
Tr.debug(tc, "=============== BEGIN STACK TRACE ================");
String stackTrace = Arrays.toString(Thread.currentThread().getStackTrace()).replace(',', '\n');
Tr.debug(tc, stackTrace);
Tr.debug(tc, "================ END STACK TRACE =================");

}

public void setWebAuthenticator(ServiceReference<WebAuthenticator> ref) {
outputStackTraceToDebug();
String cn = (String) ref.getProperty(KEY_COMPONENT_NAME);
webAuthenticatorRef.putReference(cn, ref);
if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
Tr.debug(tc, "setWebAuthenticator, adding key component name [" + cn + "].");
}
if (cn.equals(JASPI_SERVICE_COMPONENT_NAME)) {
if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
Tr.debug(tc, "setWebAuthenticator, enabling JASPI service for component name [" + JASPI_SERVICE_COMPONENT_NAME + "].");
}
isJaspiEnabled = true;
}
}

public void unsetWebAuthenticator(ServiceReference<WebAuthenticator> ref) {
String cn = (String) ref.getProperty(KEY_COMPONENT_NAME);
webAuthenticatorRef.removeReference(cn, ref);
if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
Tr.debug(tc, "unsetWebAuthenticator, removing key component name [" + cn + "].");
}
if (cn.equals(JASPI_SERVICE_COMPONENT_NAME)) {
if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
Tr.debug(tc, "setWebAuthenticator, disabling JASPI service for component name [" + JASPI_SERVICE_COMPONENT_NAME + "].");
}
isJaspiEnabled = false;
}
}
Expand Down Expand Up @@ -667,6 +689,7 @@ private void resetSyncToOSThread(WebSecurityContext webSecurityContext) throws T

private void performSecurityChecks(HttpServletRequest req, HttpServletResponse resp, Subject receivedSubject,
WebSecurityContext webSecurityContext, SecurityMetadata securityMetadata) throws SecurityViolationException, IOException {
outputStackTraceToDebug();
String uriName = new URLHandler(webAppSecConfig).getServletURI(req);

savedSubject = receivedSubject;
Expand Down Expand Up @@ -736,6 +759,12 @@ private WebReply handleJaspi(Subject receivedSubject,
}
boolean isUnprotected = false;
if (authResult == null || (authResult.getStatus() != AuthResult.SUCCESS && webAppSecConfig.allowFailOver())) {
// at this point, if we have specified we want to override HAM processing, then
// return null here so that the parent method can drop down into
// "normal processing" for authentication from server.xml
if (webAppSecConfig.isOverrideHAMProcessing() == true) {
return null;
}
// if client cert is not processed or failed and allowFailOver is configured.
// set unprotected flag if the target url is not protected or assigned to everyone role.
isUnprotected = (unprotectedResource(webRequest) == PERMIT_REPLY);
Expand Down Expand Up @@ -1415,13 +1444,13 @@ private MatchResponse getMatchResponse(HttpServletRequest req, String uriName, S

protected String getApplicationName() {
ComponentMetaData cmd = ComponentMetaDataAccessorImpl.getComponentMetaDataAccessor().getComponentMetaData();
WebModuleMetaData wmmd = (WebModuleMetaData) ((WebComponentMetaData) cmd).getModuleMetaData();
WebModuleMetaData wmmd = ((WebModuleMetaData) cmd.getModuleMetaData());
return wmmd.getConfiguration().getApplicationName();
}

protected String getModuleName() {
ComponentMetaData cmd = ComponentMetaDataAccessorImpl.getComponentMetaDataAccessor().getComponentMetaData();
WebModuleMetaData wmmd = (WebModuleMetaData) ((WebComponentMetaData) cmd).getModuleMetaData();
WebModuleMetaData wmmd = ((WebModuleMetaData) cmd.getModuleMetaData());
return wmmd.getConfiguration().getModuleName();
}

Expand All @@ -1431,7 +1460,7 @@ public SecurityMetadata getSecurityMetadata() {

protected void setSecurityMetadata(SecurityMetadata secMetadata) {
ComponentMetaData cmd = ComponentMetaDataAccessorImpl.getComponentMetaDataAccessor().getComponentMetaData();
WebModuleMetaData wmmd = (WebModuleMetaData) ((WebComponentMetaData) cmd).getModuleMetaData();
WebModuleMetaData wmmd = ((WebModuleMetaData) cmd.getModuleMetaData());
wmmd.setSecurityMetaData(secMetadata);
}

Expand Down Expand Up @@ -1552,7 +1581,7 @@ protected WebAppConfig getWebAppConfig() {
WebAppConfig wac = null;
ComponentMetaData cmd = ComponentMetaDataAccessorImpl.getComponentMetaDataAccessor().getComponentMetaData();
if (cmd instanceof WebComponentMetaData) { // Only get the header for web modules, i.e. not for EJB
WebModuleMetaData wmmd = (WebModuleMetaData) ((WebComponentMetaData) cmd).getModuleMetaData();
WebModuleMetaData wmmd = ((WebModuleMetaData) cmd.getModuleMetaData());
wac = wmmd.getConfiguration();
if (!(wac instanceof com.ibm.ws.webcontainer.osgi.webapp.WebAppConfiguration)) {
wac = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public interface WebAppSecurityConfig {

boolean isUseAuthenticationDataForUnprotectedResourceEnabled();

boolean isOverrideHAMProcessing();

/**
* Calculates the delta between this WebAppSecurityConfig and the provided
* WebAppSecurityConfig. The values returned are the values from this Object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public class WebAppSecurityConfigImpl implements WebAppSecurityConfig {
public static final String CFG_KEY_PARTITIONED_COOKIE = "partitionedCookie";
public static final String CFG_KEY_USE_CONTEXT_ROOT_FOR_SSO_COOKIE_PATH = "useContextRootForSSOCookiePath";
public static final String CFG_KEY_MAX_CONTENT_LENGTH_TO_SAVE_POST_PARAMETERS = "postParamMaxRequestBodySize";
public static final String CFG_KEY_OVERRIDE_HAM_PROCESSING = "overrideHAMProcessing";

// New attributes must update getChangedProperties method
private final Boolean logoutOnHttpSessionExpire;
Expand Down Expand Up @@ -107,6 +108,7 @@ public class WebAppSecurityConfigImpl implements WebAppSecurityConfig {
private Boolean partitionedCookie = null; // in BETA, mark as final once GA'ed
private final Boolean useContextRootForSSOCookiePath;
private final Long postParamMaxRequestBodySize;
private final Boolean overrideHAMProcessing;

protected final AtomicServiceReference<WsLocationAdmin> locationAdminRef;
protected final AtomicServiceReference<SecurityService> securityServiceRef;
Expand Down Expand Up @@ -149,6 +151,7 @@ public class WebAppSecurityConfigImpl implements WebAppSecurityConfig {
put(CFG_KEY_PARTITIONED_COOKIE, "partitionedCookie");
put(CFG_KEY_USE_CONTEXT_ROOT_FOR_SSO_COOKIE_PATH, "useContextRootForSSOCookiePath");
put(CFG_KEY_MAX_CONTENT_LENGTH_TO_SAVE_POST_PARAMETERS, "postParamMaxRequestBodySize");
put(CFG_KEY_OVERRIDE_HAM_PROCESSING, "overrideHAMProcessing");
}
};

Expand Down Expand Up @@ -194,9 +197,10 @@ public WebAppSecurityConfigImpl(Map<String, Object> newProperties,
sameSiteCookie = (String) newProperties.get(CFG_KEY_SAME_SITE_COOKIE);
useContextRootForSSOCookiePath = (Boolean) newProperties.get(CFG_KEY_USE_CONTEXT_ROOT_FOR_SSO_COOKIE_PATH);
postParamMaxRequestBodySize = (Long) newProperties.get(CFG_KEY_MAX_CONTENT_LENGTH_TO_SAVE_POST_PARAMETERS);
overrideHAMProcessing = (Boolean) newProperties.get(CFG_KEY_OVERRIDE_HAM_PROCESSING);

String partValue = (String) newProperties.get(CFG_KEY_PARTITIONED_COOKIE);
if ("true".equalsIgnoreCase(partValue)||"false".equalsIgnoreCase(partValue)) {
if ("true".equalsIgnoreCase(partValue) || "false".equalsIgnoreCase(partValue)) {
// we want partitionedCookie to be null unless the value is true or false
// defer is the default value which mean that the channel config determines the partitioned value
// if the value is true / false then this config was explicltly set by the user
Expand Down Expand Up @@ -615,8 +619,8 @@ public Boolean getPartitionedCookie() {

@Override
public boolean isPartitionedCookie() {
if (partitionedCookie!=null && partitionedCookie==Boolean.TRUE) {
return true;
if (partitionedCookie != null && partitionedCookie == Boolean.TRUE) {
return true;
}
return false;
}
Expand All @@ -631,17 +635,21 @@ public long postParamMaxRequestBodySize() {
return postParamMaxRequestBodySize.longValue();
}

@Override
public boolean isOverrideHAMProcessing() {
return overrideHAMProcessing != null ? overrideHAMProcessing.booleanValue() : false;
}

// This method is for config users that need to know if an admin has provided a true/false or no value for a
// boolean config attribute. The current infrastructure does not properly support this
public static Boolean getBooleanValue(String attribute, String strValue) {
Boolean retVal = null;
if (strValue!=null && strValue.length()>0) {
//only values that config gives us are true/false/defer
if ("true".equalsIgnoreCase(strValue) || "false".equalsIgnoreCase(strValue)) {
retVal = Boolean.valueOf(strValue);
}
}
return(retVal);
Boolean retVal = null;
if (strValue != null && strValue.length() > 0) {
//only values that config gives us are true/false/defer
if ("true".equalsIgnoreCase(strValue) || "false".equalsIgnoreCase(strValue)) {
retVal = Boolean.valueOf(strValue);
}
}
return (retVal);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,35 @@ private WebRequest createWebRequest(String authMethod, final boolean accessPrecl
return webRequest;
}

/**
* Test method for verifying overrideHAMProcessing configuration is properly loaded
* into the collaborator via the configuration flow from the server.xml properties.
*
* NOTE: Ideally, we would test WebAppSecurityCollaboratorImpl.performSecurityChecks(), but
* that would require the method to be made public or protected and registering a real JASPIC
* service (which is complex).
*/
@Test
public void testOverrideHAMProcessingConfiguration_LoadedCorrectly() {
// test with skipJaspi enabled
configProps.put(WebAppSecurityConfigImpl.CFG_KEY_OVERRIDE_HAM_PROCESSING, true);
setupCollaborator(new WebAppSecurityCollaboratorImplTestDouble(), cc, configProps);
assertTrue("When skipJaspi is configured as true, isSkipJaspi() should return true",
secColl.webAppSecConfig.isOverrideHAMProcessing());

// test with skipJaspi disabled
configProps.put(WebAppSecurityConfigImpl.CFG_KEY_OVERRIDE_HAM_PROCESSING, false);
setupCollaborator(new WebAppSecurityCollaboratorImplTestDouble(), cc, configProps);
assertFalse("When skipJaspi is configured as false, isSkipJaspi() should return false",
secColl.webAppSecConfig.isOverrideHAMProcessing());

// test default behaviour (not set)
configProps.remove(WebAppSecurityConfigImpl.CFG_KEY_OVERRIDE_HAM_PROCESSING);
setupCollaborator(new WebAppSecurityCollaboratorImplTestDouble(), cc, configProps);
assertFalse("When skipJaspi is not configured, isSkipJaspi() should return false by default",
secColl.webAppSecConfig.isOverrideHAMProcessing());
}

/**
* Test method for {@link com.ibm.ws.webcontainer.security.internal.WebAppSecurityCollaboratorImpl#authorize(com.ibm.ws.webcontainer.security.internal.AuthenticationResult,
* java.lang.String, java.lang.String, javax.security.auth.Subject, java.util.List<String>)} .
Expand Down
Loading