diff --git a/tck/common/pom.xml b/tck/common/pom.xml
index fb55045..3791f50 100644
--- a/tck/common/pom.xml
+++ b/tck/common/pom.xml
@@ -1,6 +1,6 @@
- profile-spi
+ spi
- 11
+ 17UTF-8
@@ -134,8 +134,8 @@
org.omnifaces.arquillian
- glassfish-client-ee9
- 1.0
+ glassfish-client-ee10
+ 1.4test
@@ -172,21 +172,21 @@
jakarta.enterprisejakarta.enterprise.cdi-api
- 4.0.0
+ 4.1.0providedjakarta.validationjakarta.validation-api
- 3.0.1
+ 3.1.0providedjakarta.ejbjakarta.ejb-api
- 4.0.0
+ 4.0.1providedtrue
@@ -194,7 +194,7 @@
jakarta.annotationjakarta.annotation-api
- 2.1.0
+ 3.0.0provided
@@ -203,7 +203,6 @@
junitjunit
- 4.13.2test
@@ -236,7 +235,7 @@
org.htmlunithtmlunit
- 3.11.0
+ 4.0.0test
@@ -267,7 +266,7 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 3.10.1
+ 3.13.0org.apache.maven.plugins
@@ -277,12 +276,12 @@
org.apache.maven.pluginsmaven-dependency-plugin
- 3.2.0
+ 3.6.1org.apache.maven.pluginsmaven-failsafe-plugin
- 3.0.0-M5
+ 3.2.5org.apache.maven.plugins
@@ -295,7 +294,6 @@
org.apache.maven.pluginsmaven-enforcer-plugin
- 3.0.0enforce-maven
@@ -305,7 +303,7 @@
- 3.6.3
+ 3.8.6
@@ -327,12 +325,12 @@
org.apache.maven.pluginsmaven-resources-plugin
- 3.2.0
+ 3.3.1org.apache.maven.pluginsmaven-surefire-plugin
- 3.0.0-M5
+ 3.2.5false
@@ -384,7 +382,7 @@
org.apache.maven.pluginsmaven-surefire-report-plugin
- 3.0.0-M6
+ 3.2.5truetrue
@@ -423,6 +421,14 @@
1.4test
+
+
+
+ org.glassfish.epicyro
+ epicyro
+ 3.1.0-SNAPSHOT
+ test
+
@@ -753,21 +759,5 @@
true
-
-
- old-tck
-
-
- true
-
-
-
-
- old-tck
-
-
diff --git a/tck/profile-spi/pom.xml b/tck/profile-spi/pom.xml
index a96b45b..1b6ce5c 100644
--- a/tck/profile-spi/pom.xml
+++ b/tck/profile-spi/pom.xml
@@ -33,6 +33,11 @@
+
+ jakarta.enterprise.concurrent
+ jakarta.enterprise.concurrent-api
+ 3.1.0
+ org.jakartaeejaspic-common
@@ -43,6 +48,16 @@
jakarta.jws-api3.0.0
+
+ org.glassfish.metro
+ webservices-rt
+ 4.0.3
+
+
+ org.glassfish.main.security
+ webservices.security
+ 8.0.0-SNAPSHOT
+ jakarta.xml.wsjakarta.xml.ws-api
@@ -130,7 +145,7 @@
${basedir}/src/main/webapp/WEB-INF/HelloService.wsdl
- http://localhost:8080/jaxws-endpoint/EBookStoreImplService?wsdl
+ http://localhost:8080/spitests_servlet_web/HelloService?wsdltrue${basedir}/src/main/java
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ServerCallbackSupport.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ServerCallbackSupport.java
index 0ca115c..21ce839 100644
--- a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ServerCallbackSupport.java
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ServerCallbackSupport.java
@@ -370,7 +370,7 @@ private boolean GroupPrincipalCallbackSupport() {
// however, for the case of mandatory authen, we will want
// to create a CPC using a username as opposed to a null principal.
- Subject subject = clientSubject; // new Subject();
+ Subject subject = clientSubject != null? clientSubject : new Subject();
String strArray[] = { "Administrator" };
GroupPrincipalCallback groupPrincipalCallback = new GroupPrincipalCallback(subject, strArray);
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/SOAPTSServerAuthConfig.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/SOAPTSServerAuthConfig.java
new file mode 100644
index 0000000..ce2c7e8
--- /dev/null
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/SOAPTSServerAuthConfig.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SERVLET;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SOAP;
+import static java.util.logging.Level.FINE;
+import static java.util.logging.Level.INFO;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.xml.soap.MimeHeaders;
+import jakarta.xml.soap.Name;
+import jakarta.xml.soap.Node;
+import jakarta.xml.soap.SOAPBody;
+import jakarta.xml.soap.SOAPElement;
+import jakarta.xml.soap.SOAPEnvelope;
+import jakarta.xml.soap.SOAPException;
+import jakarta.xml.soap.SOAPMessage;
+import jakarta.xml.soap.SOAPPart;
+import java.util.Iterator;
+import java.util.Map;
+import javax.security.auth.callback.CallbackHandler;
+
+public class SOAPTSServerAuthConfig extends TSServerAuthConfig {
+
+ protected SOAPTSServerAuthConfig(String layer, String applicationCtxt, CallbackHandler cbkHandler, Map props) {
+ super(layer, applicationCtxt, cbkHandler, props);
+ }
+
+ public SOAPTSServerAuthConfig(String layer, String applicationCtxt, CallbackHandler cbkHandler, Map props, TSLogger tsLogger) {
+ super(layer, applicationCtxt, cbkHandler, props);
+
+ if (tsLogger != null) {
+ logger = tsLogger;
+ }
+
+ String str = "TSServerAuthConfig called for layer=" + layer + " : appContext=" + applicationCtxt;
+ logger.log(INFO, str);
+ }
+
+ @Override
+ public String getAuthContextID(MessageInfo messageInfo) {
+ logger.log(INFO, "getAuthContextID called");
+ String authContextID = null;
+
+ if (messageLayer.equals(LAYER_SOAP)) {
+ authContextID = getOpName((SOAPMessage) messageInfo.getRequestMessage());
+
+ logger.log(INFO, "getAuthContextID() called for layer=" + messageLayer + " shows AuthContextId=" + authContextID);
+
+ } else if (messageLayer.equals(LAYER_SERVLET)) {
+ super.getAuthContextID(messageInfo);
+ }
+
+ return authContextID;
+ }
+
+ private String getOpName(SOAPMessage message) {
+ if (message == null) {
+ return null;
+ }
+
+ String opName = null;
+
+ // First look for a SOAPAction header.
+ // this is what .net uses to identify the operation
+ MimeHeaders headers = message.getMimeHeaders();
+ if (headers != null) {
+ String[] actions = headers.getHeader("SOAPAction");
+ if (actions != null && actions.length > 0) {
+ opName = actions[0];
+ if (opName != null && opName.equals("\"\"")) {
+ opName = null;
+ }
+ }
+ }
+
+ // If that doesn't work then we default to trying the name
+ // of the first child element of the SOAP envelope.
+ if (opName == null) {
+ Name name = getName(message);
+ if (name != null) {
+ opName = name.getLocalName();
+ }
+ }
+
+ return opName;
+ }
+
+ private Name getName(SOAPMessage message) {
+ SOAPPart soap = message.getSOAPPart();
+ if (soap == null) {
+ return null;
+ }
+
+ try {
+ SOAPEnvelope envelope = soap.getEnvelope();
+ if (envelope == null) {
+ return null;
+ }
+
+ SOAPBody body = envelope.getBody();
+ if (body == null) {
+ return null;
+ }
+
+ Iterator childElements = body.getChildElements();
+ while (childElements.hasNext()) {
+ if (childElements.next() instanceof SOAPElement soapElement) {
+ return soapElement.getElementName();
+ }
+ }
+ } catch (SOAPException se) {
+ logger.log(FINE, "WSS: Unable to get SOAP envelope", se);
+ }
+
+ return null;
+ }
+
+}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProvider.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProvider.java
index 8f27fe7..c36386e 100644
--- a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProvider.java
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProvider.java
@@ -16,6 +16,8 @@
package ee.jakarta.tck.authentication.test.basic.sam.config;
+import static java.util.logging.Level.INFO;
+
import ee.jakarta.tck.authentication.test.basic.sam.AuthDataCallbackHandler;
import ee.jakarta.tck.authentication.test.basic.sam.TSFileHandler;
import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
@@ -27,7 +29,6 @@
import jakarta.security.auth.message.config.ServerAuthConfig;
import java.util.HashMap;
import java.util.Map;
-import java.util.logging.Level;
import javax.security.auth.callback.CallbackHandler;
/**
@@ -37,7 +38,7 @@
public class TSAuthConfigProvider implements jakarta.security.auth.message.config.AuthConfigProvider {
private static TSLogger logger;
- private static Map properties;
+ private static Map properties;
private HashMap clientAuthConfigMap = new HashMap();
private HashMap serverAuthConfigMap = new HashMap();
@@ -103,7 +104,7 @@ public TSAuthConfigProvider(Map props, AuthConfigFactory factory, TSLogger tsLog
public ClientAuthConfig getClientAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException {
String logStr = "TSAuthConfigProvider.getClientAuthConfig called for " + "layer=" + layer + " : " + "appContext=" + appContext;
- logger.log(Level.INFO, logStr);
+ logger.log(INFO, logStr);
try {
if (handler == null) {
@@ -160,7 +161,7 @@ public ClientAuthConfig getClientAuthConfig(String layer, String appContext, Cal
public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException {
String logStr = "TSAuthConfigProvider.getServerAuthConfig called for " + "layer=" + layer + " : " + "appContext=" + appContext;
- logger.log(Level.INFO, logStr);
+ logger.log(INFO, logStr);
try {
if ((!layer.equals(JASPICData.LAYER_SERVLET)) && (handler == null)) {
@@ -173,13 +174,13 @@ public ServerAuthConfig getServerAuthConfig(String layer, String appContext, Cal
// that we should NOT have a null cbh passed in
String msg = "FAILURE: layer=" + layer + " appContext=" + appContext;
msg += " getServerAuthConfig() received CallbackHandler=null";
- logger.log(Level.INFO, msg);
+ logger.log(INFO, msg);
}
ServerAuthConfig serverAuthConfig = null;
if (JASPICData.LAYER_SOAP.equals(layer)) {
- // serverAuthConfig = new SOAPTSServerAuthConfig(layer, appContext, handler, properties, logger);
+ serverAuthConfig = new SOAPTSServerAuthConfig(layer, appContext, handler, properties, logger);
} else {
serverAuthConfig = new TSServerAuthConfig(layer, appContext, handler, properties, logger);
}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthContext.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthContext.java
index 5da45ba..db66f38 100644
--- a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthContext.java
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthContext.java
@@ -16,15 +16,21 @@
package ee.jakarta.tck.authentication.test.basic.sam.config;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SERVLET;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SOAP;
+import static java.util.logging.Level.INFO;
+
import ee.jakarta.tck.authentication.test.basic.sam.module.servlet.TSClientAuthModule;
-import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSAuthExceptionClientAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSFailureClientAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSSendFailureClientAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSSendSuccessClientAuthModule;
import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
import jakarta.security.auth.message.AuthException;
import jakarta.security.auth.message.AuthStatus;
import jakarta.security.auth.message.MessageInfo;
import jakarta.security.auth.message.module.ClientAuthModule;
import java.util.Map;
-import java.util.logging.Level;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
@@ -36,65 +42,53 @@ public class TSClientAuthContext implements jakarta.security.auth.message.config
private static ClientAuthModule clientAuthModule;
private static TSLogger logger;
- private static String messageLayer = null;
- private static String appContext = null;
- private static CallbackHandler handler = null;
- private static String operation = null;
- private static Subject clientSubject = null;
- private static Map properties = null;
public TSClientAuthContext() {
}
public TSClientAuthContext(String messageLayer, String appContext, CallbackHandler handler, String operation, Subject clientSubject,
- Map properties, TSLogger tsLogger) throws AuthException {
+ Map properties, TSLogger tsLogger) throws AuthException {
this(messageLayer, appContext, handler, operation, clientSubject, properties);
+
logger = tsLogger;
ClientAuthModule cam = null;
- logger.log(Level.INFO, "TSClientAuthContext called");
+ logger.log(INFO, "TSClientAuthContext called");
- // pass TSlogger to TSServerAuthModule through properties
+ // Pass TSlogger to TSServerAuthModule through properties
properties.put("TSLogger", logger);
- if (messageLayer.equals(JASPICData.LAYER_SOAP)) {
-// if (appContext.indexOf("SendSuccessHello") > -1) {
-// cam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSSendSuccessClientAuthModule();
-// cam.initialize(null, null, handler, properties);
-//
-// } else if (appContext.indexOf("SendFailureHello") > -1) {
-// cam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSSendFailureClientAuthModule();
-// cam.initialize(null, null, handler, properties);
-//
-// } else if (appContext.indexOf("FailureHello") > -1) {
-// cam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSFailureClientAuthModule();
-// cam.initialize(null, null, handler, properties);
-//
-// } else if (appContext.indexOf("AuthExceptionHello") > -1) {
-// cam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSAuthExceptionClientAuthModule();
-// cam.initialize(null, null, handler, properties);
-//
-// } else {
-// cam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSClientAuthModule();
-// cam.initialize(null, null, handler, properties);
-// }
- } else if (messageLayer.equals(JASPICData.LAYER_SERVLET)) {
+ if (messageLayer.equals(LAYER_SOAP)) {
+ if (appContext.indexOf("SendSuccessHello") > -1) {
+ cam = new TSSendSuccessClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("SendFailureHello") > -1) {
+ cam = new TSSendFailureClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("FailureHello") > -1) {
+ cam = new TSFailureClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("AuthExceptionHello") > -1) {
+ cam = new TSAuthExceptionClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+
+ } else {
+ cam = new ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+ }
+ } else if (messageLayer.equals(LAYER_SERVLET)) {
cam = new TSClientAuthModule();
cam.initialize(null, null, handler, properties);
}
clientAuthModule = cam;
-
}
- private TSClientAuthContext(String layer, String appContxt, CallbackHandler hndler, String operatn, Subject cliSubject, Map props) throws AuthException {
- messageLayer = layer;
- appContext = appContxt;
- handler = hndler;
- operation = operatn;
- clientSubject = cliSubject;
- properties = props;
+ private TSClientAuthContext(String layer, String appContxt, CallbackHandler hndler, String operatn, Subject cliSubject, Map props) throws AuthException {
}
@@ -142,7 +136,7 @@ private TSClientAuthContext(String layer, String appContxt, CallbackHandler hndl
*/
@Override
public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
- logger.log(Level.INFO, "TSClientAuthContext.secureRequest called");
+ logger.log(INFO, "TSClientAuthContext.secureRequest called");
return clientAuthModule.secureRequest(messageInfo, clientSubject);
}
@@ -193,7 +187,8 @@ public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject)
*/
@Override
public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
- logger.log(Level.INFO, "TSClientAuthContext.validateResponse called");
+ logger.log(INFO, "TSClientAuthContext.validateResponse called");
+
return clientAuthModule.validateResponse(messageInfo, clientSubject, serviceSubject);
}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthContext.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthContext.java
index acb6c86..6f4902e 100644
--- a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthContext.java
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthContext.java
@@ -16,10 +16,17 @@
package ee.jakarta.tck.authentication.test.basic.sam.config;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SERVLET;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SOAP;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.SVC_SUBJECT_KEY;
import static java.util.logging.Level.INFO;
import ee.jakarta.tck.authentication.test.basic.sam.module.servlet.TSServerAuthModule;
import ee.jakarta.tck.authentication.test.basic.sam.module.servlet.TSServletWrapperSAM;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSAuthExceptionServerAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSFailureServerAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSSendFailureServerAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSSendSuccessServerAuthModule;
import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
import jakarta.security.auth.message.AuthException;
@@ -46,9 +53,12 @@ public class TSServerAuthContext implements jakarta.security.auth.message.config
private static ServerAuthModule serverAuthModule;
private static String messageLayer;
- private static Map properties;
+ private static Map properties;
private static TSLogger logger;
+
+ private static String soapUPTokenAppContext = "HelloService HelloPort";
private static String servletUPTokenAppContext = "spitests_servlet_web";
+
private static MessageInfo messageInfoFromVerifyReq;
private static boolean isMandatory = false;
@@ -100,40 +110,38 @@ public String getID() {
// Note: We could also choose auth modules based on appContext but
// MessageLayer seems to be the ideal candidate for choosing
// auth modules.
- if (messageLayer.equals(JASPICData.LAYER_SOAP)) {
-// sam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSServerAuthModule();
-//
-// if (appContext.equals(soapUPTokenAppContext)) {
-//
-// sam.initialize(requestMessagePolicy, responseMessagePolicy, handler, properties);
-// } else if (appContext.indexOf("SendSuccessHello") > -1) {
-// sam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSSendSuccessServerAuthModule();
-// sam.initialize(null, null, handler, properties);
-//
-// } else if (appContext.indexOf("SendFailureHello") > -1) {
-// sam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSSendFailureServerAuthModule();
-// sam.initialize(null, null, handler, properties);
-//
-// } else if (appContext.indexOf("FailureHello") > -1) {
-// sam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSFailureServerAuthModule();
-// sam.initialize(null, null, handler, properties);
-//
-// } else if (appContext.indexOf("AuthExceptionHello") > -1) {
-// sam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSAuthExceptionServerAuthModule();
-// sam.initialize(null, null, handler, properties);
-//
-// } else {
-// sam = new com.sun.ts.tests.jaspic.tssv.module.soap.TSServerAuthModule();
-// sam.initialize(null, null, handler, properties);
-// }
-
- } else if (messageLayer.equals(JASPICData.LAYER_SERVLET)) {
+ if (messageLayer.equals(LAYER_SOAP)) {
+
+ if (appContext.equals(soapUPTokenAppContext)) {
+ sam = new ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSServerAuthModule();
+ sam.initialize(requestMessagePolicy, responseMessagePolicy, handler, properties);
+ } else if (appContext.indexOf("SendSuccessHello") > -1) {
+ sam = new TSSendSuccessServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("SendFailureHello") > -1) {
+ sam = new TSSendFailureServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("FailureHello") > -1) {
+ sam = new TSFailureServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("AuthExceptionHello") > -1) {
+ sam = new TSAuthExceptionServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+
+ } else {
+ sam = new ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+ }
+
+ } else if (messageLayer.equals(LAYER_SERVLET)) {
System.out.println("AppContext =" + appContext);
if (appContext.contains(servletUPTokenAppContext) && operation.contains("WrapperServlet")) {
sam = new TSServletWrapperSAM();
sam.initialize(requestMessagePolicy, responseMessagePolicy, handler, properties);
-
} else if (appContext.contains(servletUPTokenAppContext)) {
sam = new TSServerAuthModule();
sam.initialize(requestMessagePolicy, responseMessagePolicy, handler, properties);
@@ -149,7 +157,7 @@ public String getID() {
/*
* This should be private so that we can be sure people pass a valid TSLogger into the public constructor.
*/
- private TSServerAuthContext(String layer, String appCtxt, CallbackHandler callbackHandler, String optn, Subject clientSubject, Map props) throws AuthException {
+ private TSServerAuthContext(String layer, String appCtxt, CallbackHandler callbackHandler, String optn, Subject clientSubject, Map props) throws AuthException {
messageLayer = layer;
properties = props;
}
@@ -525,37 +533,31 @@ public void verifyMessageInfoObjsMatch(MessageInfo messageInfo) {
*
*/
public void verifySecureRespServiceSubject(Subject serviceSubject) {
- String msg = "";
- String key = JASPICData.SVC_SUBJECT_KEY;
- Subject value = (Subject) properties.get(key);
+ Subject subjectFromProperties = (Subject) properties.get(SVC_SUBJECT_KEY);
- if (value != null) {
- msg = "got a non-null subject out of the map";
- logger.log(INFO, msg);
+ if (subjectFromProperties != null) {
+ logger.log(INFO, "Got a non-null subject out of the map");
if (serviceSubject == null) {
- msg = "FAILURE detected - SecureResponse ServiceSubjects should be the same and are not.";
- } else if (value.equals(serviceSubject)) {
- msg = "SecureResponse ServiceSubjects correctly matched.";
+ logger.log(INFO, "FAILURE detected - SecureResponse ServiceSubjects should be the same and are not.");
+ } else if (subjectFromProperties.equals(serviceSubject)) {
+ logger.log(INFO, "SecureResponse ServiceSubjects correctly matched.");
} else {
- // if here, serviceSubjects dont match but should
- msg = "FAILURE detected - SecureResponse ServiceSubjects should be the same and are not.";
+ // If here, service subjects don't match but should
+ logger.log(INFO, "FAILURE detected - SecureResponse ServiceSubjects should be the same and are not.");
}
- logger.log(INFO, msg);
- if ((serviceSubject != null) && (value.equals(serviceSubject))) {
- // to help verify assertion JASPI:SPEC:313 (per spec section 2.1.5.2):
+ if ((serviceSubject != null) && (subjectFromProperties.equals(serviceSubject))) {
+ // To help verify assertion JASPI:SPEC:313 (per spec section 2.1.5.2):
// If a non-null Subject was used to call the ServerAuthContext
// the same Subject must be passed as the serviceSubject in this
// call. If a non-null serviceSubject is used in this call, it
// must not be read-only
if (serviceSubject.isReadOnly()) {
- // should not get here.
- msg = "FAILURE detected - SecureResponse ServiceSubjects should not be read-only.";
- logger.log(INFO, msg);
+ // Should not get here.
+ logger.log(INFO, "FAILURE detected - SecureResponse ServiceSubjects should not be read-only.");
} else {
- msg = "Valid SecureResponse ServiceSubjects - it was not read-only.";
- logger.log(INFO, msg);
+ logger.log(INFO, "Valid SecureResponse ServiceSubjects - it was not read-only.");
}
}
}
@@ -577,6 +579,7 @@ public void verifySecureRespServiceSubject(Subject serviceSubject) {
@Override
public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
logger.log(INFO, "TSServerAuthContext.cleanSubject called");
+
serverAuthModule.cleanSubject(messageInfo, subject);
}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/SamAutoRegistrationListener.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AuthFactoryContainerInitializer.java
similarity index 58%
rename from tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/SamAutoRegistrationListener.java
rename to tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AuthFactoryContainerInitializer.java
index 1d942cf..2fc4315 100644
--- a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/SamAutoRegistrationListener.java
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AuthFactoryContainerInitializer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2022 Contributors to the Eclipse Foundation
+ * Copyright (c) 2024 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -13,29 +13,20 @@
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-package ee.jakarta.tck.authentication.test.basic.sam;
+package ee.jakarta.tck.authentication.test.basic.servlet;
import ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigFactory;
import jakarta.security.auth.message.config.AuthConfigFactory;
-import jakarta.servlet.ServletContextEvent;
-import jakarta.servlet.ServletContextListener;
-import jakarta.servlet.annotation.WebListener;
+import jakarta.servlet.ServletContainerInitializer;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import java.util.Set;
-/**
- *
- * @author Arjan Tijms
- *
- */
-@WebListener
-public class SamAutoRegistrationListener implements ServletContextListener {
+public class AuthFactoryContainerInitializer implements ServletContainerInitializer {
@Override
- public void contextInitialized(ServletContextEvent sce) {
+ public void onStartup(Set> c, ServletContext ctx) throws ServletException {
AuthConfigFactory.setFactory(new TSAuthConfigFactory());
-
-
-// AuthConfigFactory.getFactory()
-// .registerServerAuthModule(new TestServerAuthModule(), sce.getServletContext());
}
-}
\ No newline at end of file
+}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/IdUtil.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/IdUtil.java
index 0d670db..f5a5d3b 100644
--- a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/IdUtil.java
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/IdUtil.java
@@ -21,6 +21,8 @@
import ee.jakarta.tck.authentication.test.basic.sam.TSFileHandler;
import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
import ee.jakarta.tck.authentication.test.common.logging.server.TSXMLFormatter;
+import jakarta.enterprise.concurrent.ManagedExecutorDefinition;
+import jakarta.enterprise.concurrent.ManagedScheduledExecutorDefinition;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ModTestServlet.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ModTestServlet.java
index 2977ff9..352caa8 100644
--- a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ModTestServlet.java
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ModTestServlet.java
@@ -16,7 +16,11 @@
package ee.jakarta.tck.authentication.test.basic.servlet;
+import jakarta.annotation.Resource;
import jakarta.annotation.security.DeclareRoles;
+import jakarta.enterprise.concurrent.ContextServiceDefinition;
+import jakarta.enterprise.concurrent.ManagedExecutorDefinition;
+import jakarta.enterprise.concurrent.ManagedExecutorService;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.HttpConstraint;
import jakarta.servlet.annotation.HttpMethodConstraint;
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/Hello.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/Hello.java
new file mode 100644
index 0000000..833e58f
--- /dev/null
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/Hello.java
@@ -0,0 +1,42 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import jakarta.jws.WebMethod;
+import jakarta.jws.WebParam;
+import jakarta.jws.WebResult;
+import jakarta.jws.WebService;
+import jakarta.xml.bind.annotation.XmlSeeAlso;
+import jakarta.xml.ws.Action;
+import jakarta.xml.ws.RequestWrapper;
+import jakarta.xml.ws.ResponseWrapper;
+
+
+/**
+ * This class was generated by the XML-WS Tools.
+ * XML-WS Tools 4.0.1
+ * Generated source version: 3.0
+ *
+ */
+@WebService(name = "Hello", targetNamespace = "http://soap.basic.test.authentication.tck.jakarta.ee/")
+@XmlSeeAlso({
+ ObjectFactory.class
+})
+public interface Hello {
+
+
+ /**
+ *
+ * @param arg0
+ * @return
+ * returns java.lang.String
+ */
+ @WebMethod
+ @WebResult(targetNamespace = "")
+ @RequestWrapper(localName = "sayHelloProtected", targetNamespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", className = "ee.jakarta.tck.authentication.test.basic.soap.SayHelloProtected")
+ @ResponseWrapper(localName = "sayHelloProtectedResponse", targetNamespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", className = "ee.jakarta.tck.authentication.test.basic.soap.SayHelloProtectedResponse")
+ @Action(input = "http://soap.basic.test.authentication.tck.jakarta.ee/Hello/sayHelloProtectedRequest", output = "http://soap.basic.test.authentication.tck.jakarta.ee/Hello/sayHelloProtectedResponse")
+ public String sayHelloProtected(
+ @WebParam(name = "arg0", targetNamespace = "")
+ String arg0);
+
+}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/HelloService.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/HelloService.java
new file mode 100644
index 0000000..311f85a
--- /dev/null
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/HelloService.java
@@ -0,0 +1,94 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import javax.xml.namespace.QName;
+import jakarta.xml.ws.Service;
+import jakarta.xml.ws.WebEndpoint;
+import jakarta.xml.ws.WebServiceClient;
+import jakarta.xml.ws.WebServiceException;
+import jakarta.xml.ws.WebServiceFeature;
+
+
+/**
+ * This class was generated by the XML-WS Tools.
+ * XML-WS Tools 4.0.1
+ * Generated source version: 3.0
+ *
+ */
+@WebServiceClient(name = "HelloService", targetNamespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", wsdlLocation = "http://localhost:8080/spitests_servlet_web/HelloService?wsdl")
+public class HelloService
+ extends Service
+{
+
+ private static final URL HELLOSERVICE_WSDL_LOCATION;
+ private static final WebServiceException HELLOSERVICE_EXCEPTION;
+ private static final QName HELLOSERVICE_QNAME = new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloService");
+
+ static {
+ URL url = null;
+ WebServiceException e = null;
+ try {
+ url = new URL("http://localhost:8080/spitests_servlet_web/HelloService?wsdl");
+ } catch (MalformedURLException ex) {
+ e = new WebServiceException(ex);
+ }
+ HELLOSERVICE_WSDL_LOCATION = url;
+ HELLOSERVICE_EXCEPTION = e;
+ }
+
+ public HelloService() {
+ super(__getWsdlLocation(), HELLOSERVICE_QNAME);
+ }
+
+ public HelloService(WebServiceFeature... features) {
+ super(__getWsdlLocation(), HELLOSERVICE_QNAME, features);
+ }
+
+ public HelloService(URL wsdlLocation) {
+ super(wsdlLocation, HELLOSERVICE_QNAME);
+ }
+
+ public HelloService(URL wsdlLocation, WebServiceFeature... features) {
+ super(wsdlLocation, HELLOSERVICE_QNAME, features);
+ }
+
+ public HelloService(URL wsdlLocation, QName serviceName) {
+ super(wsdlLocation, serviceName);
+ }
+
+ public HelloService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
+ super(wsdlLocation, serviceName, features);
+ }
+
+ /**
+ *
+ * @return
+ * returns Hello
+ */
+ @WebEndpoint(name = "HelloPort")
+ public Hello getHelloPort() {
+ return super.getPort(new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloPort"), Hello.class);
+ }
+
+ /**
+ *
+ * @param features
+ * A list of {@link jakarta.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features parameter will have their default values.
+ * @return
+ * returns Hello
+ */
+ @WebEndpoint(name = "HelloPort")
+ public Hello getHelloPort(WebServiceFeature... features) {
+ return super.getPort(new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloPort"), Hello.class, features);
+ }
+
+ private static URL __getWsdlLocation() {
+ if (HELLOSERVICE_EXCEPTION!= null) {
+ throw HELLOSERVICE_EXCEPTION;
+ }
+ return HELLOSERVICE_WSDL_LOCATION;
+ }
+
+}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/ObjectFactory.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/ObjectFactory.java
new file mode 100644
index 0000000..2c49164
--- /dev/null
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/ObjectFactory.java
@@ -0,0 +1,83 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import javax.xml.namespace.QName;
+import jakarta.xml.bind.JAXBElement;
+import jakarta.xml.bind.annotation.XmlElementDecl;
+import jakarta.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the ee.jakarta.tck.authentication.test.basic.soap package.
+ *
An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private static final QName _SayHelloProtected_QNAME = new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "sayHelloProtected");
+ private static final QName _SayHelloProtectedResponse_QNAME = new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "sayHelloProtectedResponse");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: ee.jakarta.tck.authentication.test.basic.soap
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link SayHelloProtected }
+ *
+ * @return
+ * the new instance of {@link SayHelloProtected }
+ */
+ public SayHelloProtected createSayHelloProtected() {
+ return new SayHelloProtected();
+ }
+
+ /**
+ * Create an instance of {@link SayHelloProtectedResponse }
+ *
+ * @return
+ * the new instance of {@link SayHelloProtectedResponse }
+ */
+ public SayHelloProtectedResponse createSayHelloProtectedResponse() {
+ return new SayHelloProtectedResponse();
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link SayHelloProtected }{@code >}
+ *
+ * @param value
+ * Java instance representing xml element's value.
+ * @return
+ * the new instance of {@link JAXBElement }{@code <}{@link SayHelloProtected }{@code >}
+ */
+ @XmlElementDecl(namespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", name = "sayHelloProtected")
+ public JAXBElement createSayHelloProtected(SayHelloProtected value) {
+ return new JAXBElement<>(_SayHelloProtected_QNAME, SayHelloProtected.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link SayHelloProtectedResponse }{@code >}
+ *
+ * @param value
+ * Java instance representing xml element's value.
+ * @return
+ * the new instance of {@link JAXBElement }{@code <}{@link SayHelloProtectedResponse }{@code >}
+ */
+ @XmlElementDecl(namespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", name = "sayHelloProtectedResponse")
+ public JAXBElement createSayHelloProtectedResponse(SayHelloProtectedResponse value) {
+ return new JAXBElement<>(_SayHelloProtectedResponse_QNAME, SayHelloProtectedResponse.class, null, value);
+ }
+
+}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtected.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtected.java
new file mode 100644
index 0000000..c052d6f
--- /dev/null
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtected.java
@@ -0,0 +1,60 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlType;
+
+
+/**
+ *
Java class for sayHelloProtected complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
{@code
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * }
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "sayHelloProtected", propOrder = {
+ "arg0"
+})
+public class SayHelloProtected {
+
+ protected String arg0;
+
+ /**
+ * Gets the value of the arg0 property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getArg0() {
+ return arg0;
+ }
+
+ /**
+ * Sets the value of the arg0 property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setArg0(String value) {
+ this.arg0 = value;
+ }
+
+}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtectedResponse.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtectedResponse.java
new file mode 100644
index 0000000..47e8d0e
--- /dev/null
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtectedResponse.java
@@ -0,0 +1,62 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlType;
+
+
+/**
+ *
Java class for sayHelloProtectedResponse complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
{@code
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * }
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "sayHelloProtectedResponse", propOrder = {
+ "_return"
+})
+public class SayHelloProtectedResponse {
+
+ @XmlElement(name = "return")
+ protected String _return;
+
+ /**
+ * Gets the value of the return property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getReturn() {
+ return _return;
+ }
+
+ /**
+ * Sets the value of the return property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setReturn(String value) {
+ this._return = value;
+ }
+
+}
diff --git a/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/package-info.java b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/package-info.java
new file mode 100644
index 0000000..0cb79e8
--- /dev/null
+++ b/tck/profile-spi/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/package-info.java
@@ -0,0 +1,2 @@
+@jakarta.xml.bind.annotation.XmlSchema(namespace = "http://soap.basic.test.authentication.tck.jakarta.ee/")
+package ee.jakarta.tck.authentication.test.basic.soap;
diff --git a/tck/profile-spi/src/main/resources/META-INF/services/com.sun.xml.ws.assembler.metro.dev.ClientPipelineHook b/tck/profile-spi/src/main/resources/META-INF/services/com.sun.xml.ws.assembler.metro.dev.ClientPipelineHook
new file mode 100644
index 0000000..1d320b3
--- /dev/null
+++ b/tck/profile-spi/src/main/resources/META-INF/services/com.sun.xml.ws.assembler.metro.dev.ClientPipelineHook
@@ -0,0 +1 @@
+com.sun.enterprise.security.webservices.client.ClientSecurityPipeCreator
\ No newline at end of file
diff --git a/tck/profile-spi/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer b/tck/profile-spi/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer
new file mode 100644
index 0000000..7a4388c
--- /dev/null
+++ b/tck/profile-spi/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer
@@ -0,0 +1 @@
+ee.jakarta.tck.authentication.test.basic.servlet.AuthFactoryContainerInitializer
\ No newline at end of file
diff --git a/tck/profile-spi/src/main/webapp/WEB-INF/HelloService.wsdl b/tck/profile-spi/src/main/webapp/WEB-INF/HelloService.wsdl
index ae434bf..7a83418 100644
--- a/tck/profile-spi/src/main/webapp/WEB-INF/HelloService.wsdl
+++ b/tck/profile-spi/src/main/webapp/WEB-INF/HelloService.wsdl
@@ -3,12 +3,12 @@
RI's version is Eclipse Metro/4.0.0-M4 (RELEASE-4.0.0-M4-3da3fb9; 2022-03-31T12:28:52+0000)
XMLWS-Impl/4.0.0-M4 XMLWS-API/4.0.0 XMLB-Impl/4.0.0-M4 XMLB-API/4.0.0 git-revision#3da3fb9. -->
@@ -16,7 +16,7 @@
@@ -32,10 +32,10 @@
diff --git a/tck/profile-spi/src/main/webapp/WEB-INF/HelloService_schema1.xsd b/tck/profile-spi/src/main/webapp/WEB-INF/HelloService_schema1.xsd
index da88ee9..94b5d77 100644
--- a/tck/profile-spi/src/main/webapp/WEB-INF/HelloService_schema1.xsd
+++ b/tck/profile-spi/src/main/webapp/WEB-INF/HelloService_schema1.xsd
@@ -1,5 +1,5 @@
-
+
diff --git a/tck/profile-spi/src/main/webapp/WEB-INF/soap-web.xml b/tck/profile-spi/src/main/webapp/WEB-INF/soap-web.xml
new file mode 100644
index 0000000..c8cbc07
--- /dev/null
+++ b/tck/profile-spi/src/main/webapp/WEB-INF/soap-web.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+ soap_app
+
+
+ Hello
+ ee.jakarta.tck.authentication.test.basic.soap.HelloImpl
+ 0
+
+ ADM
+ Administrator
+
+
+
+ Hello
+ /Hello
+
+
+
+ 54
+
+
+
+ the administrator role
+ Administrator
+
+
diff --git a/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletProfileSPITest.java b/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletProfileSPITest.java
index c5935f7..29ec0fd 100644
--- a/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletProfileSPITest.java
+++ b/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletProfileSPITest.java
@@ -3,13 +3,16 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import ee.jakarta.tck.authentication.test.basic.servlet.AuthFactoryContainerInitializer;
import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
import ee.jakarta.tck.authentication.test.common.ArquillianBase;
import ee.jakarta.tck.authentication.test.common.logging.client.LogFileProcessor;
+import jakarta.servlet.ServletContainerInitializer;
import org.htmlunit.WebResponse;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,7 +40,12 @@ public class ServletProfileSPITest extends ArquillianBase {
@Deployment(testable = false)
public static Archive> createDeployment() {
- return defaultWebArchive("spitests_servlet_web");
+ WebArchive archive = defaultWebArchive("spitests_servlet_web");
+ archive.addAsServiceProvider(ServletContainerInitializer.class, AuthFactoryContainerInitializer.class);
+
+ System.out.println(archive.toString(true));
+
+ return archive;
}
/**
diff --git a/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/UnitTest.java b/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletUnitTest.java
similarity index 99%
rename from tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/UnitTest.java
rename to tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletUnitTest.java
index c4d0a15..205d1d0 100644
--- a/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/UnitTest.java
+++ b/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletUnitTest.java
@@ -41,9 +41,9 @@
* @author Arjan Tijms
*
*/
-public class UnitTest {
+public class ServletUnitTest {
- Logger logger = Logger.getLogger(UnitTest.class.getName());
+ Logger logger = Logger.getLogger(ServletUnitTest.class.getName());
/**
*
diff --git a/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapProfileSPITest.java b/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapProfileSPITest.java
new file mode 100644
index 0000000..b0864dc
--- /dev/null
+++ b/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapProfileSPITest.java
@@ -0,0 +1,866 @@
+package ee.jakarta.tck.authentication.test.basic;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.TSSV_ACF;
+import static jakarta.security.auth.message.config.AuthConfigFactory.DEFAULT_FACTORY_SECURITY_PROPERTY;
+import static org.junit.Assert.assertTrue;
+
+import com.sun.xml.ws.api.client.ClientPipelineHook;
+import ee.jakarta.tck.authentication.test.basic.servlet.AuthFactoryContainerInitializer;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.basic.soap.HelloService;
+import ee.jakarta.tck.authentication.test.common.ArquillianBase;
+import ee.jakarta.tck.authentication.test.common.logging.client.LogFileProcessor;
+import ee.jakarta.tck.authentication.test.common.logging.client.TestUtil;
+import jakarta.servlet.ServletContainerInitializer;
+import java.net.URL;
+import java.security.Security;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import javax.xml.namespace.QName;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+/**
+ * This tests a large number of SPI assertions from the Servlet profile.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class SoapProfileSPITest extends ArquillianBase {
+
+ private static boolean setUpIsDone = false;
+
+ String logicalHostName = "localhost";
+ String expectedAppContextId = "localhost /Hello_web/Hello";
+
+ // this must be the decoded context path corresponding to the web module
+ private String contextPath = "/" + JASPICData.SCP_CONTEXT_PATH;
+ private String openToAllServletPath = "OpenToAllServlet";
+
+ private String appContext = System.getProperty("logical.hostname.servlet") + " " + contextPath;
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ LogFileProcessor clientLogProcessor = new LogFileProcessor(true);
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ WebArchive archive = defaultWebArchive("Hello_web");
+ archive.addAsServiceProvider(ServletContainerInitializer.class, AuthFactoryContainerInitializer.class);
+ archive.addAsWebInfResource(resource("soap-web.xml"), "web.xml");
+
+ System.out.println(archive.toString(true));
+
+ return archive;
+ }
+
+
+ @Before
+ public void runOnce() throws Exception {
+ if (setUpIsDone) {
+ return;
+ }
+
+ Security.setProperty(DEFAULT_FACTORY_SECURITY_PROPERTY, TSSV_ACF);
+ Optional optionalHook = ServiceLoader.load(ClientPipelineHook.class).findFirst();
+ if (optionalHook.isPresent()) {
+ int a;
+ a = 4;
+ }
+
+ HelloService helloService = new HelloService(
+ new URL(getBase(), "Hello?wsdl"),
+ new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloService"));
+
+ String text = helloService.getHelloPort().sayHelloProtected("Raja");
+ TestUtil.logMsg("Got Output : " + text);
+
+ logProcessor.fetchLogs();
+
+ setUpIsDone = true;
+ }
+
+ @Before
+ public void fetchLogs() {
+ logProcessor.fetchLogs();
+ clientLogProcessor.fetchLogs();
+ }
+
+
+ // ### Client side tests
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ValidateResponse
+ *
+ * @assertion_ids: JASPIC:SPEC:42
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether ClientAuthContext.validateResponse() is called
+ *
+ * Description The runtime must invoke ClientAuthContext.validateResponse()
+ *
+ */
+ @Test
+ public void ValidateResponse() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ "validateResponse failed : " + "ClientAuthContext.validateResponse not called",
+ clientLogProcessor.verifyLogContains("TSClientAuthContext.validateResponse called"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ClientAuthContext
+ *
+ * @assertion_ids: JASPIC:SPEC:34; JASPIC:JAVADOC:72; JASPIC:JAVADOC:97; JASPIC:JAVADOC:98
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether ClientAuthConfig.getAuthContext() is called
+ *
+ * Description The runtime must invoke clientAuthConfig().getAuthContext() to obtain the ClientAuthContext.
+ *
+ */
+ @Test
+ public void ClientAuthContext() {
+ String args[] = { "service/HelloService", getBase() + "Hello" };
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "ClientAuthContext failed : " + "clientAuthConfig.getAuthContext not called",
+ clientLogProcessor.verifyLogContainsOneOfSubString(args, "TSClientAuthConfig.getAuthContext: layer=SOAP : appContext="));
+ }
+
+ /**
+ * @testName: NameAndPasswordCallbackSupport
+ *
+ * @assertion_ids: JASPIC:SPEC:123; JASPIC:JAVADOC:103
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether CallbackHandler for client runtime supports
+ * NameCallback and PasswordCallback
+ *
+ * Description Unless the client runtime is embedded in a server runtime (e.g.; an invocation of a web service by a
+ * servlet running in a Servlet container), The CallbackHandler passed to ClientAuthModule.initialize must support the
+ * following callbacks: NameCallback, PasswordCallback
+ *
+ */
+ @Test
+ public void NameAndPasswordCallbackSupport() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContains(
+ "In SOAP : ClientRuntime CallbackHandler supports NameCallback",
+ "In SOAP : ClientRuntime CallbackHandler supports PasswordCallback"));
+ }
+
+ /**
+ * @testName: ClientRuntimeCommonCallbackSupport
+ *
+ * @assertion_ids: JASPIC:SPEC:114; JASPIC:JAVADOC:35; JASPIC:JAVADOC:36; JASPIC:JAVADOC:49; JASPIC:JAVADOC:51;
+ * JASPIC:JAVADOC:54; JASPIC:JAVADOC:63; JASPIC:JAVADOC:65; JASPIC:JAVADOC:68; JASPIC:JAVADOC:69; JASPIC:JAVADOC:71;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether CallbackHandler for client runtime supports
+ * CertStoreCallback, PrivateKeyCallback, SecretKeyCallback, TrustStoreCallback
+ *
+ * Description
+ *
+ * The CallbackHandler passed to the initialize method of an authentication module should support the following
+ * callbacks, and it must be possible to configure the runtime such that the CallbackHandler passed at module
+ * initialization module supports the following callbacks (in addition to any others required to be supported by the
+ * applicable internal profile): CertStoreCallback, PrivateKeyCallback, SecretKeyCallback, TrustStoreCallback
+ *
+ *
+ */
+ @Test
+ public void ClientRuntimeCommonCallbackSupport() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContains(
+ "In SOAP : ClientRuntime CallbackHandler supports CertStoreCallback",
+ "In SOAP : ClientRuntime CallbackHandler supports PrivateKeyCallback",
+ "In SOAP : ClientRuntime CallbackHandler supports SecretKeyCallback",
+ "In SOAP : ClientRuntime CallbackHandler supports TrustStoreCallback"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACPClientAuthConfig
+ *
+ * @assertion_ids: JASPIC:SPEC:124; JASPIC:JAVADOC:77
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether the arguments(layer and appcontextId) passed to
+ * obtain AuthConfigProvider is same as the arguments used in calling getClientAuthConfig.
+ *
+ * Description
+ *
+ * If a non-null AuthConfigProvider is returned (by the call to getConfigProvider), the messaging runtime must call
+ * getClientAuthConfig on the provider to obtain the authentication context configuration object pertaining to the
+ * application context at the layer. The layer and appContext arguments of the call to getClientAuthConfig must be the
+ * same as those used to acquire the provider.
+ *
+ *
+ */
+ @Test
+ public void ACPClientAuthConfig() {
+ String args[] = { "service/HelloService", getBase() + "Hello" };
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContainsOneOfSubString(args, "TSAuthConfigFactory.getConfigProvider returned non-null provider for" + " Layer : SOAP and AppContext :"));
+
+ // ACPClientAuthConfig : Same layer and appContextId used
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContainsOneOfSubString(args, "TSAuthConfigProvider.getClientAuthConfig called for " + "layer=SOAP : appContext="));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: CACRequestResponse
+ *
+ * @assertion_ids: JASPIC:SPEC:130; JASPIC:JAVADOC:7; JASPIC:JAVADOC:9; JASPIC:SPEC:19; JASPIC:SPEC:23; JASPIC:SPEC:129;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify whether for a non-null ClientAuthContext, secureRequest
+ * and validateResponse are called properly.
+ *
+ * Description
+ *
+ * If the client runtime obtained a non-null ClientAuthContext by using the operation identifier corresponding to the
+ * request message, then at point (1) in the message processing model, the runtime must call secureRequest on the
+ * ClientAuthContext, and at point (4) the runtime must call validateResponse on the ClientAuthContext.
+ *
+ *
+ */
+ @Test
+ public void CACRequestResponse() {
+ // Verify whether the log contains required messages.
+ assertTrue(clientLogProcessor.verifyLogContains(
+ "TSClientAuthConfig.getAuthContext: returned non-null" + " ClientAuthContext for operationId=sayHelloProtected",
+ "TSClientAuthContext.secureRequest called",
+ "TSClientAuthContext.validateResponse called"));
+ }
+
+
+
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ClientRuntimeMessageInfoMap
+ *
+ * @assertion_ids: JASPIC:SPEC:133; JASPIC:JAVADOC:7
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify whether the Map in messageInfo object passed to
+ * secureRequest and validateResponse contains the right value for key jakarta.xml.ws.wsdl.service
+ *
+ * Description This profile requires that the message processing runtime establish the following key-value pairs within
+ * the Map of the MessageInfo passed in the calls to secureRequest and validateResponse Key=jakarta.xml.ws.wsdl.service
+ * Value= the value of the qualified service name, represented as a javax.xml.namespace.QName
+ *
+ */
+ @Test
+ public void ClientRuntimeMessageInfoMap() {
+ QName expectedQName = new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloService");
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContains(
+ "TSClientAuthModule.secureRequest messageInfo :" + "jakarta.xml.ws.wsdl.service=" + expectedQName.toString(),
+ "TSClientAuthModule.validateResponse messageInfo :" + "jakarta.xml.ws.wsdl.service=" + expectedQName.toString()));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ClientAppContextId
+ *
+ * @assertion_ids: JASPIC:SPEC:208
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify whether for the client side appilcation context
+ * Identifier is correctly used by the runtime.
+ *
+ * Description A Client application context Identifier must be the String value composed by concatenating the client
+ * scope identifier, a blank separator character, and the client reference to the service. The clien scope identifier is
+ * not testable but we can check the client reference to the service.
+ *
+ */
+ @Test
+ public void ClientAppContextId() {
+ String args[] = { "service/HelloService", getBase() + "Hello" };
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContainsOneOfSubString(args,
+ "TSAuthConfigProvider.getClientAuthConfig called for " + "layer=SOAP : appContext="));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ClientAuthConfig
+ *
+ * @assertion_ids: JASPIC:SPEC:11; JASPIC:SPEC:12 ; JASPIC:SPEC:16;
+ * JASPIC:JAVADOC:92; JASPIC:JAVADOC:93; JASPIC:SPEC:110;
+ * JASPIC:SPEC:111
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether AuthConfigProvider.ClientAuthConfig is
+ * called in the server.
+ *
+ * Description The runtime must invoke
+ * AuthConfigProvider.getClientAuthConfig() to obtain the
+ * AuthConfig. The runtime must also specify
+ * appropriate(non-null) layer(i.e for this test case "SOAP"
+ * layer) and application context identifiers in its call to
+ * getClientAuthConfig.
+ *
+ */
+ @Test
+ public void ClientAuthConfig() {
+ String args[] = { "service/HelloService", getBase() + "Hello" };
+
+ // verify whether the log contains required messages.
+ assertTrue(
+ "ClientAuthConfig failed : " + "AuthConfigProvider.getClientAuthConfig not called",
+ clientLogProcessor.verifyLogContainsOneOfSubString(args,
+ "TSAuthConfigProvider.getClientAuthConfig called for layer=SOAP : appContext="));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: SecureRequest
+ *
+ * @assertion_ids: JASPIC:SPEC:35; JASPIC:JAVADOC:5; JASPIC:SPEC:36;
+ * JASPIC:JAVADOC:75
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether ClientAuthContext.secureRequest() is called
+ *
+ * Description The runtime must invoke
+ * ClientAuthContext.secureRequest()
+ *
+ */
+ @Test
+ public void SecureRequest() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "SecureRequest failed : " + "ClientAuthContext.secureRequest not called",
+ clientLogProcessor.verifyLogContains("TSClientAuthContext.secureRequest called"));
+ }
+
+
+
+ // ### Server side ###
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: GetConfigProvider
+ *
+ * @assertion_ids: JASPIC:SPEC:8; JASPIC:SPEC:14; JASPIC:SPEC:116; JASPIC:SPEC:117; JASPIC:JAVADOC:77;
+ * JASPIC:JAVADOC:79; JASPIC:JAVADOC:80; JASPIC:JAVADOC:84; JASPIC:JAVADOC:85; JASPIC:JAVADOC:91; JASPIC:SPEC:110;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether AuthConfigFactory.getConfigProvider is called
+ * in the server.
+ *
+ * Description The runtime must invoke AuthConfigFactory.getConfigProvider to obtain the AuthConfigProvider. The runtime
+ * must also specify appropriate(non-null) layer and application context identifiers in its call to getConfigProvider.
+ *
+ */
+ @Test
+ public void GetConfigProvider() {
+ assertTrue(
+ "GetConfigProvider failed : " + "AuthConfigFactory.getConfigProvider not called",
+ logProcessor.verifyLogContains(
+ "TSAuthConfigFactory.getConfigProvider called",
+ "getConfigProvider called for Layer : SOAP and AppContext :" + expectedAppContextId ));
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: GetFactory
+ *
+ * @assertion_ids: JASPIC:SPEC:7; JASPIC:SPEC:10; JASPIC:JAVADOC:77;
+ * JASPIC:JAVADOC:80; JASPIC:JAVADOC:84; JASPIC:JAVADOC:79;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether AuthConfigFactory.getConfigProvider is
+ * called in the server.
+ *
+ * Description The runtime must invoke
+ * AuthConfigFactory.getConfigProvider to obtain the
+ * AuthConfigProvider. By calling getConfigProvider, we can
+ * assume getFactory() was called.
+ *
+ */
+ @Test
+ public void GetFactory() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "GetFactory failed : " + "AuthConfigFactory.getFactory not called",
+ logProcessor.verifyLogContains("TSAuthConfigFactory.getFactory called Indirectly"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ServerAuthConfig
+ *
+ * @assertion_ids: JASPIC:SPEC:11; JASPIC:SPEC:13 ; JASPIC:SPEC:16;
+ * JASPIC:JAVADOC:95
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether provider.getServerAuthConfig is called in
+ * the server.
+ *
+ * Description The runtime must invoke
+ * AuthConfigProvider.getServerAuthConfig() to obtain the
+ * AuthConfig. The runtime must also specify
+ * appropriate(non-null) layer(i.e for this test case "SOAP"
+ * layer) and application context identifiers in its call to
+ * getServerAuthConfig.
+ *
+ */
+ @Test
+ public void ServerAuthConfig() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "ServerAuthConfig failed : " + "AuthConfigProvider.getServerAuthConfig not called",
+ logProcessor.verifyLogContains(
+ "TSAuthConfigProvider.getServerAuthConfig called for layer=SOAP" +
+ " : appContext=" + expectedAppContextId));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ValidateRequest
+ *
+ * @assertion_ids: JASPIC:SPEC:50; JASPIC:JAVADOC:16; JASPIC:JAVADOC:17;
+ * JASPIC:JAVADOC:23; JASPIC:SPEC:23; JASPIC:SPEC:19
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether ServerAuthContext.validateRequest() is
+ * called
+ *
+ * Description The runtime must invoke
+ * ServerAuthContext.validateRequest()
+ *
+ */
+ @Test
+ public void ValidateRequest() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "ValidateRequest failed : " + "ServerAuthContext.validateRequest not called",
+ logProcessor.verifyLogContains("TSServerAuthContext.validateRequest called"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: SecureResponse
+ *
+ * @assertion_ids: JASPIC:SPEC:59; JASPIC:JAVADOC:16; JASPIC:JAVADOC:17;
+ * JASPIC:JAVADOC:23; JASPIC:JAVADOC:26
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether ServerAuthContext.secureResponse() is called
+ *
+ * Description The runtime must invoke
+ * ServerAuthContext.secureResponse()
+ *
+ */
+ @Test
+ public void SecureResponse() {
+ // verify whether the log contains required messages.
+ assertTrue("SecureResponse failed : " + "ServerAuthContext.secureResponse not called",
+ logProcessor.verifyLogContains("TSServerAuthContext.secureResponse called"));
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ServerAuthContext
+ *
+ * @assertion_ids: JASPIC:SPEC:34; JASPIC:JAVADOC:100; JASPIC:SPEC:153;
+ * JASPIC:SPEC:156; JASPIC:JAVADOC:101
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether ServerAuthConfig.getAuthContext() is called
+ *
+ * Description The runtime must invoke
+ * serverAuthConfig().getAuthContext() to obtain the
+ * ServerAuthContext.
+ *
+ */
+ @Test
+ public void ServerAuthContext() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ "TSServerAuthConfig.getAuthContext: layer=SOAP : appContext=" + expectedAppContextId,
+ logProcessor.verifyLogContains(
+ "TSServerAuthConfig.getAuthContext: layer=SOAP : appContext=" + expectedAppContextId));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: MessageInfo
+ *
+ * @assertion_ids: JASPIC:SPEC:35; JASPIC:SPEC:44; JASPIC:JAVADOC:5;
+ * JASPIC:SPEC:112; JASPIC:JAVADOC:9; JASPIC:JAVADOC:10;
+ * JASPIC:JAVADOC:11; JASPIC:JAVADOC:28; JASPIC:SPEC:23;
+ * JASPIC:SPEC:19; JASPIC:SPEC:36; JASPIC:SPEC:37;
+ * JASPIC:SPEC:43; JASPIC:SPEC:51; JASPIC:SPEC:113;
+ * JASPIC:SPEC:131; JASPIC:SPEC:132;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether the messageInfo passed to secureRequest()
+ * validateRequest(), secureResponse() and validateResponse()
+ * contiains right values for getRequestMessage() and
+ * getResponseMessage() as per the spec.
+ *
+ * 3. clientSubject - a Subject that represents the source of
+ * the service request, or null.
+ *
+ * Description The MessageInfo argument used in any call made
+ * by the message processing runtime to secureRequest,
+ * validateResponse, validateRequest, or secureResponse must
+ * have been initialized such that the non-null objects
+ * returned by the getRequestMessage and getResponseMessage
+ * methods of the MessageInfo are an instanceof
+ * jakarta.xml.soap.SOAPMessage.
+ *
+ *
+ */
+ @Test
+ public void MessageInfo() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ "MessageInfo failed : " + "The request and response messages contains incorrect values",
+ logProcessor.verifyLogContains(
+ // "secureRequest : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage",
+ "validateRequest : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage",
+ "secureResponse : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage",
+ "secureResponse : MessageInfo.getResponseMessage() is of type jakarta.xml.soap.SOAPMessage"
+
+
+ ));
+
+ // "validateResponse : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage",
+ //"validateResponse : MessageInfo.getResponseMessage() is of type jakarta.xml.soap.SOAPMessage"
+ }
+
+ /**
+ * @testName: ServerRuntimeCommonCallbackSupport
+ *
+ * @assertion_ids: JASPIC:SPEC:114; JASPIC:JAVADOC:35; JASPIC:JAVADOC:36;
+ * JASPIC:JAVADOC:49; JASPIC:JAVADOC:51; JASPIC:JAVADOC:54;
+ * JASPIC:JAVADOC:63; JASPIC:JAVADOC:65; JASPIC:JAVADOC:68;
+ * JASPIC:JAVADOC:69; JASPIC:JAVADOC:71; JASPIC:JAVADOC:106
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether CallbackHandler for server runtime supports
+ * CertStoreCallback, PrivateKeyCallback, SecretKeyCallback,
+ * TrustStoreCallback
+ *
+ * Description
+ *
+ * The CallbackHandler passed to the initialize method of an
+ * authentication module should support the following
+ * callbacks, and it must be possible to configure the runtime
+ * such that the CallbackHandler passed at module
+ * initialization module supports the following callbacks (in
+ * addition to any others required to be supported by the
+ * applicable internal profile): CertStoreCallback,
+ * PrivateKeyCallback, SecretKeyCallback, TrustStoreCallback
+ *
+ *
+ */
+ @Test
+ public void ServerRuntimeCommonCallbackSupport() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "In SOAP : ServerRuntime CallbackHandler supports CertStoreCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports PrivateKeyCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports SecretKeyCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports TrustStoreCallback"));
+ }
+
+ /**
+ * @testName: ServerRuntimeCallbackSupport
+ *
+ * @assertion_ids: JASPIC:SPEC:114; JASPIC:SPEC:149; JASPIC:JAVADOC:38;
+ * JASPIC:JAVADOC:39; JASPIC:JAVADOC:40; JASPIC:JAVADOC:42;
+ * JASPIC:JAVADOC:43; JASPIC:JAVADOC:44; JASPIC:JAVADOC:46;
+ * JASPIC:JAVADOC:30; JASPIC:JAVADOC:41; JASPIC:JAVADOC:45
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether CallbackHandler for server runtime supports
+ * CallerPrincipalCallback, GroupPrincipalCallback and
+ * PasswordValidationCallback
+ *
+ * Description
+ *
+ * The CallbackHandler passed to the
+ * ServerAuthModule.initialize must support the following
+ * callbacks,
+ *
+ * CallerPrincipalCallback, GroupPrincipalCallback,
+ * PasswordValidationCallback
+ *
+ *
+ */
+ @Test
+ public void ServerRuntimeCallbackSupport() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "In SOAP : ServerRuntime CallbackHandler supports CallerPrincipalCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports GroupPrincipalCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports PasswordValidationCallback"));
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: OperationId
+ *
+ * @assertion_ids: JASPIC:SPEC:121; JASPIC:SPEC:125; JASPIC:JAVADOC:73
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether the operationId is "sayHelloProtected"
+ *
+ * Description
+ *
+ * If getOperation returns a non-null operation identifier,
+ * then the operation identifier must be the String value
+ * corresponding to the operation name appearing in the
+ * service description (i.e., WSDL).
+ *
+ * When its getOperation method is called, any authentication
+ * context configuration object obtained for the SOAP layer,
+ * must attempt to derive the corresponding operation
+ * identifier value from the request message (within
+ * messageInfo).
+ *
+ *
+ */
+ @Test
+ public void OperationId() {
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "getAuthContextID() called for layer=SOAP shows AuthContextId=" +
+ "sayHelloProtected"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACPAuthContext
+ *
+ * @assertion_ids: JASPIC:SPEC:125; JASPIC:SPEC:150; JASPIC:JAVADOC:5;
+ * JASPIC:JAVADOC:28; JASPIC:JAVADOC:73; JASPIC:JAVADOC:79
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether the arguments(operation) passed to obtain
+ * getAuthContext is same as defined in Section 4.7.1
+ *
+ * Description The authentication context identifier used in
+ * the call to getAuthContext must be equivalent to the value
+ * that would be acquired by calling getAuthContextID with the
+ * MessageInfo that will be used in the corresponding call to
+ * secureRequest (by a client runtime) or validateRequest (by
+ * a server runtime).
+ *
+ */
+ @Test
+ public void ACPAuthContext() {
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "TSAuthConfigFactory.getConfigProvider returned non-null provider for" + " Layer : SOAP and AppContext :" + expectedAppContextId,
+ "TSServerAuthConfig.getAuthContext: layer=SOAP" + " : appContext=" + expectedAppContextId + " operationId=sayHelloProtected"));
+
+
+// String cArgs[] = { "service/HelloService",
+// "http://" + hostname + ":" + portnum + "/Hello_web/Hello" };
+//
+// // verify whether the log contains required messages.
+// logProcessor.verifyLogContainsOneOfSubString(cArgs,
+// "TSClientAuthConfig.getAuthContext: layer=SOAP"
+// + " : appContext=");
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACPServerAuthConfig
+ *
+ * @assertion_ids: JASPIC:SPEC:150; JASPIC:JAVADOC:79; JASPIC:JAVADOC:94
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether the arguments(layer and appcontextId) passed
+ * to obtain AuthConfigProvider is same as the arguments used
+ * in calling getServerAuthConfig.
+ *
+ * Description
+ *
+ * If a non-null AuthConfigProvider is returned (by the call
+ * to getConfigProvider), the messaging runtime must call
+ * getServerAuthConfig on the provider to obtain the
+ * authentication context configuration object pertaining to
+ * the application context at the layer. The layer and
+ * appContext arguments of the call to getServerAuthConfig
+ * must be the same as those used to acquire the provider.
+ *
+ *
+ */
+ public void ACPServerAuthConfig() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "TSAuthConfigFactory.getConfigProvider returned non-null provider for" + " Layer : SOAP and AppContext :" + expectedAppContextId,
+ "TSAuthConfigProvider.getServerAuthConfig called for " + "layer=SOAP : appContext=" + expectedAppContextId ));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: SACRequestResponse
+ *
+ * @assertion_ids: JASPIC:SPEC:130; JASPIC:JAVADOC:13; JASPIC:JAVADOC:16;
+ * JASPIC:JAVADOC:17; JASPIC:JAVADOC:23; JASPIC:JAVADOC:26;
+ * JASPIC:JAVADOC:28; JASPIC:SPEC:155;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify whether for a non-null ServerAuthContext,
+ * validateRequest and secureResponse are called properly.
+ *
+ * Description
+ *
+ * If the server runtime obtained a non-null ServerAuthContext
+ * by using the operation identifier corresponding to the
+ * request message, then at point (2) in the message
+ * processing model, the runtime must call validateRequest on
+ * the ClientAuthContext, and at point (3) the runtime must
+ * call secureResponse on the ServerAuthContext.
+ *
+ *
+ */
+ public void SACRequestResponse() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "TSServerAuthConfig.getAuthContext: returned non-null" + " ServerAuthContext for operationId=sayHelloProtected",
+ "TSServerAuthContext.validateRequest called",
+ "TSServerAuthContext.secureResponse called" ));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ServerAppContextId
+ *
+ * @assertion_ids: JASPIC:SPEC:209
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify whether for the server side appilcation context
+ * Identifier is correctly used by the runtime.
+ *
+ * Description A server application context Identifier shall
+ * be the String value composed by concatenating a logical
+ * hostname a blank separator character, and the path
+ * component of the service endpoint URI corresponding to the
+ * webservice.
+ */
+ @Test
+ public void ServerAppContextId() {
+ String args[] = {
+ logicalHostName + " /Hello_web/Hello" };
+
+ // verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContainsOneOfSubString(args,
+ "TSAuthConfigProvider.getServerAuthConfig called for " + "layer=SOAP : appContext="));
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapUnitTest.java b/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapUnitTest.java
new file mode 100644
index 0000000..a807597
--- /dev/null
+++ b/tck/profile-spi/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapUnitTest.java
@@ -0,0 +1,606 @@
+package ee.jakarta.tck.authentication.test.basic;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.TSSV_ACF;
+import static jakarta.security.auth.message.config.AuthConfigFactory.DEFAULT_FACTORY_SECURITY_PROPERTY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationEntry;
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationXMLFileProcessor;
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigFactoryForStandalone;
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSRegistrationListener;
+import ee.jakarta.tck.authentication.test.basic.servlet.CommonTests;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.AuthConfigProvider;
+import jakarta.security.auth.message.config.RegistrationListener;
+import java.security.Security;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.logging.Logger;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SoapUnitTest {
+
+ Logger logger = Logger.getLogger(SoapUnitTest.class.getName());
+
+ private String logFileLocation = System.getProperty("log.file.location");
+ private String providerConfigFileLocation = System.getProperty("provider.configuration.file");
+ private String vendorACFClass = System.getProperty("vendor.authconfig.factory");
+ private String soapAppContext = "localhost /Hello_web/Hello";
+
+ private transient ProviderConfigurationXMLFileProcessor configFileProcessor;
+
+ private Collection providerConfigurationEntriesCollection;
+
+ private CommonTests commonTests = new CommonTests();
+
+ @Before
+ public void setup() {
+ AuthConfigFactory.setFactory(null);
+ Security.setProperty(DEFAULT_FACTORY_SECURITY_PROPERTY, TSSV_ACF);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFGetFactory
+ *
+ * @assertion_ids: JASPIC:SPEC:329; JASPIC:SPEC:335; JASPIC:SPEC:7;
+ *
+ * @test_Strategy: This s mainly concerned with testing the runtimes handling of ACF as follows: - get current (CTS) ACF
+ * - switch to use different (CTS) ACF - verify calls to ACF use the newer/expected ACF - restore original ACF
+ */
+ @Test
+ public void ACFGetFactory() {
+ boolean passed = false;
+ try {
+ commonTests._ACF_getFactory();
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ *
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFSwitchFactorys
+ *
+ * @assertion_ids:
+ *
+ *
+ * @test_Strategy: This test does the following: - gets current (CTS) factory - sets the vendors ACF thus replacing the
+ * CTS ACF - verify ACF's were correctly set - reset factory back to the original CTS factory
+ *
+ * 1. Use the static setFactory method to set an ACF and this should always work. and use the getFactory to verify it
+ * worked.
+ *
+ * Description
+ *
+ */
+ @Test
+ public void ACFSwitchFactorys() {
+ boolean passed = false;
+ try {
+ commonTests._ACFSwitchFactorys(vendorACFClass);
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: testACFComesFromSecFile
+ *
+ * @assertion_ids: JASPIC:SPEC:329; JASPIC:SPEC:330;
+ *
+ * @test_Strategy: This is calling a method on the server(actually servlet) side that will invoke getFactory() to verify
+ * a non-null facotry instance is returned. It will also verify that the authconfigprovider.factory security property is
+ * properly set/used.
+ *
+ */
+ @Test
+ public void testACFComesFromSecFile() {
+ boolean passed = false;
+ try {
+ commonTests._testACFComesFromSecFile();
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFPersistentRegisterOnlyOneACP
+ *
+ * @assertion_ids: JASPIC:SPEC:329; JASPIC:SPEC:331; JASPIC:SPEC:332; JASPIC:SPEC:340; JASPIC:SPEC:341;
+ *
+ * @test_Strategy: This will make a server (actually servlet) side method call that will do the following: - load
+ * vendors ACF - (persistent) register of CTS ACP's in the vendors ACF - get list of vendors registered provider ID's -
+ * register another persistent ACP (this is standalone ACP profile) - verify another regId was added for standalone ACP
+ * - try to re-register (persistently) standalone provider - verify 2nd attempt at added standalone provider REPLACED
+ * the first but it should NOT have added another nor failed. - also confirm that regID for standalone ACP stayed the
+ * same after 1st and 2nd attempt to register standalone ACP - verify that the 2nd re-registering of ACP replaced the
+ * ACP AND the description. - unregister standalone ACP and setFactory back to CTS default
+ *
+ */
+ @Test
+ public void ACFPersistentRegisterOnlyOneACP() {
+ boolean passed = false;
+ try {
+ commonTests._ACFRegisterOnlyOneACP(logFileLocation, providerConfigFileLocation, vendorACFClass, true);
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFInMemoryRegisterOnlyOneACP
+ *
+ * @assertion_ids: JASPIC:SPEC:334; JASPIC:SPEC:342; JASPIC:SPEC:343;
+ *
+ * @test_Strategy: This will make a server (actually servlet) side method call that will do the following: - load
+ * vendors ACF - (persistent) register of CTS ACP's in the vendors ACF - get list of vendors registered provider ID's -
+ * register (in-memory) ACP (this is standalone ACP profile) - verify another regId was added for standalone ACP - try
+ * to re-register (in-memory) standalone provider - verify 2nd attempt at added standalone provider REPLACED the first
+ * but it should NOT have added another nor failed. - also confirm that regID for standalone ACP stayed the same after
+ * 1st and 2nd attempt to register standalone ACP - verify that the 2nd re-registering of ACP replaced the ACP AND the
+ * description. - unregister standalone ACP and setFactory back to CTS default
+ *
+ */
+ @Test
+ public void ACFInMemoryRegisterOnlyOneACP() {
+ boolean passed = false;
+ try {
+ commonTests._ACFRegisterOnlyOneACP(logFileLocation, providerConfigFileLocation, vendorACFClass, false);
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFUnregisterACP
+ *
+ * @assertion_ids: JASPIC:SPEC:344;
+ *
+ * @test_Strategy: This will make a server (actually servlet) side method call that will do the following: - load
+ * vendors ACF - (persistent) register of CTS ACP's in the vendors ACF - get list of vendors registered provider ID's -
+ * register (in-memory) ACP (this is standalone ACP profile) - verify another regId was added for standalone ACP -
+ * unregister the in-memory ACP we just registered - verify removeRegistration() method call returned proper boolean -
+ * verify expected # of registry eentries - verify 2nd call to removeRegistration() with regId that was previously
+ * removed and should expect return val of false
+ *
+ */
+ @Test
+ public void ACFUnregisterACP() {
+ boolean passed = false;
+ try {
+ commonTests._ACFUnregisterACP(logFileLocation, providerConfigFileLocation, vendorACFClass);
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ *
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFRemoveRegistrationWithBadId
+ *
+ * @assertion_ids: JASPIC:SPEC:345;
+ *
+ *
+ * @test_Strategy: This test verifies we get a return value of False when invoking ACF.removeRegistration(some_bad_id);
+ *
+ * 1. Use the static setFactory method to get an ACF and then attempt to invoke removeRegistration() with an invalid (ie
+ * non-existant) regId. This should return False (per javadoc).
+ *
+ * Description
+ *
+ */
+ @Test
+ public void ACFRemoveRegistrationWithBadId() {
+ boolean passed = false;
+ try {
+ commonTests._ACFRemoveRegistrationWithBadId();
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: getRegistrationContextId
+ *
+ * @assertion_ids: JASPIC:JAVADOC:77
+ *
+ * @test_Strategy: 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Use the system properties to read the TestSuite providers defined in ProviderConfigruation.xml file and register
+ * them with vendor's authconfig factory.
+ *
+ *
+ * Description This will use an appContext value that was used to register a provider, and it will see if it can use the
+ * AuthConfigFactory.RegistrationContext API to try and access the same appContext value that was used during the
+ * registration process.
+ *
+ */
+ @Test
+ public void getRegistrationContextId() {
+ String appContext = "localhost /Hello_web/Hello";
+
+ // register providers in vendor factory
+ assertTrue(register(logFileLocation, providerConfigFileLocation, vendorACFClass));
+
+ // verify we can access a given provider (any provider) appcontext id
+ boolean bVerified = false;
+
+ AuthConfigFactory acf = null;
+
+ try {
+ acf = AuthConfigFactory.getFactory();
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory.";
+ msg = msg + " Check your server side security policies.";
+ logger.info(msg);
+ ex.printStackTrace();
+ }
+
+ assertNotNull(
+ "getRegistrationContextId failed : could not get acf",
+ acf);
+
+
+ String[] regIDs = acf.getRegistrationIDs(null);
+ for (int ii = 0; ii < regIDs.length; ii++) {
+ // loop through the ACF's registration ids
+
+ if (regIDs[ii] != null) {
+ AuthConfigFactory.RegistrationContext acfReg;
+ acfReg = acf.getRegistrationContext(regIDs[ii]);
+ if (acfReg != null) {
+ logger.info("appContext = " + appContext);
+ logger.info("acfReg.getAppContext() = " + acfReg.getAppContext());
+ logger.info("layer = " + acfReg.getMessageLayer());
+ String str = acfReg.getAppContext();
+ if ((str != null) && (str.equals(appContext))) {
+ // we found our provider info
+ logger.info("Found it : RegistrationID for our ACP=" + regIDs[ii]);
+ bVerified = true;
+ break;
+ }
+ }
+ }
+ }
+
+ String msg = "Could not find appContext=" + appContext;
+ msg += " in the ACF's list of registration id info";
+
+ assertTrue(msg, bVerified);
+
+ logger.info("TestSuite Providers registration successful");
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: AuthConfigFactoryRegistration
+ *
+ * @assertion_ids: JASPIC:JAVADOC:80
+ *
+ * @test_Strategy: 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Use the system properties to read the TestSuite providers defined in ProviderConfigruation.xml file and register
+ * them with vendor's authconfig factory.
+ *
+ *
+ * Description
+ *
+ *
+ */
+ @Test
+ public void AuthConfigFactoryRegistration() {
+ assertTrue(
+ register(logFileLocation, providerConfigFileLocation, vendorACFClass));
+ }
+
+ public boolean register(String logFileLocation, String providerConfigFileLocation, String vendorACFClass) {
+ try {
+ printVerticalIndent();
+
+ // Get an instance of Vendor's AuthConfigFactory
+ AuthConfigFactory vendorFactory = getVendorAuthConfigFactory(vendorACFClass);
+
+ // Set vendor's AuthConfigFactory
+ AuthConfigFactory.setFactory(vendorFactory);
+
+ // Get system default AuthConfigFactory
+ AuthConfigFactory systemAuthConfigFactory = AuthConfigFactory.getFactory();
+
+ if (systemAuthConfigFactory != null) {
+ logger.info("Default AuthConfigFactory class name = " + systemAuthConfigFactory.getClass().getName());
+
+ } else {
+ logger.severe("Default AuthConfigFactory is null" + " can't register TestSuite Providers with null");
+ return false;
+ }
+
+ /**
+ * Read the ProviderConfiguration XML file This file contains the list of providers that needs to be loaded by the
+ * vendor's default AuthConfigFactory
+ */
+ providerConfigurationEntriesCollection = readProviderConfigurationXMLFile();
+
+ ProviderConfigurationEntry pce = null;
+
+ printVerticalIndent();
+ Iterator iterator = providerConfigurationEntriesCollection.iterator();
+ while (iterator.hasNext()) {
+ // obtain each ProviderConfigurationEntry and register it
+ // with vendor's default AuthConfigFactory
+ pce = iterator.next();
+
+ if (pce != null) {
+ logger.info("Registering Provider " + pce.getProviderClassName() + " ...");
+ systemAuthConfigFactory.registerConfigProvider(
+ pce.getProviderClassName(),
+ pce.getProperties(),
+ pce.getMessageLayer(),
+ pce.getApplicationContextId(),
+ pce.getRegistrationDescription());
+
+ logger.info("Registration Successful");
+ }
+ }
+
+ printVerticalIndent();
+
+ // Check whether the providers are registered for the right message layer
+ // and appContext
+ // verifyRegistrations(acf);
+
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory";
+ msg = msg + "or ACF.setFactory(). Check your server side security policies.";
+ logger.info(msg);
+ ex.printStackTrace();
+
+ } catch (Exception e) {
+ logger.info("Error Registering TestSuite AuthConfig Providers");
+ e.printStackTrace();
+ }
+
+ return true;
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: AuthConfigFactoryVerifyPersistence
+ *
+ * @assertion_ids: JASPIC:JAVADOC:75
+ *
+ * @test_Strategy: 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Load vendor's AuthConfigFactory and make sure the registered providers return properly for the right message layer
+ * and appContextId
+ *
+ * Note: We test the persistance behaviour for vendor's AuthConfigFactory by registering providers from a persisted
+ * file, then we verify the registrations went correctly.
+ *
+ * Description
+ *
+ *
+ */
+ public void AuthConfigFactoryVerifyPersistence() {
+ try {
+
+ // register providers in vendor factory
+ assertTrue(register(logFileLocation, providerConfigFileLocation, vendorACFClass));
+
+ // Get system default AuthConfigFactory
+ AuthConfigFactory acf = AuthConfigFactory.getFactory();
+
+ if (acf != null) {
+ logger.info("Default AuthConfigFactory class name = " + acf.getClass().getName());
+
+ assertTrue(verifyRegistrations(acf));
+
+ } else {
+ logger.severe("Default AuthConfigFactory is null" + " can't verify registrations for TestSuite Providers");
+ }
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory.";
+ msg = msg + " Check your server side security policies.";
+ logger.info(msg);
+ ex.printStackTrace();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @keywords: jaspic_soap
+ *
+ * @testName: AuthConfigFactorySetFactory
+ *
+ * @assertion_ids: JASPIC:SPEC:7; JASPIC:SPEC:10; JASPIC:JAVADOC:87; JASPIC:JAVADOC:80
+ *
+ * @test_Strategy: 1. Use the static setFactory method to set an ACF and this should always work.
+ *
+ * Description This method uses the getFactory() method to get the current factory, then it uses the setFactory() to
+ * change the current ACF. This method then verifies that the ACF's were indeed changed. We know that the setFactory()
+ * works as it is used in the bootstrap process - but this is an additional level of testing that allows us to set the
+ * factory in a slightly different manner than the bootstrap (eg reading it out of the java.security file.
+ */
+ @Test
+ public void AuthConfigFactorySetFactory() {
+ // Get current AuthConfigFactory
+ AuthConfigFactory currentAcf = AuthConfigFactory.getFactory();
+
+ assertNotNull(
+ "FAILURE - Could not get current AuthConfigFactory.",
+ currentAcf);
+
+ String currentACFClass = currentAcf.getClass().getName();
+ logger.info("currentACFClass = " + currentACFClass);
+
+ // Set our ACF to a new/different AuthConfigFactory
+ TSAuthConfigFactoryForStandalone newAcf = new TSAuthConfigFactoryForStandalone();
+ AuthConfigFactory.setFactory(newAcf);
+ String newACFClass = newAcf.getClass().getName();
+ logger.info("newACFClass = " + newACFClass);
+
+ // Verify our calls to getFactory() are getting the newly set factory
+ // instance and not the original ACF instance
+ AuthConfigFactory testAcf = AuthConfigFactory.getFactory();
+
+ assertNotNull(
+ "FAILURE - Could not get newly set AuthConfigFactory.",
+ testAcf);
+
+ String newlySetACFClass = testAcf.getClass().getName();
+ logger.info("newlySetACFClass = " + newlySetACFClass);
+
+ assertEquals(
+ "FAILURE - our current ACF does not match our newly set ACF",
+ newACFClass, newlySetACFClass);
+
+ logger.info("newlySetACFClass == newACFClass == " + newACFClass);
+
+ // Restore original factory class
+ AuthConfigFactory.setFactory(currentAcf);
+
+ logger.info("AuthConfigFactorySetFactory : PASSED");
+ }
+
+
+
+ private void printVerticalIndent() {
+ logger.info("**********************************************************");
+ logger.info("\n");
+ }
+
+ /**
+ * This method instantiates and returns a AuthConfigFactory based on the specified className
+ */
+ private AuthConfigFactory getVendorAuthConfigFactory(String className) {
+ AuthConfigFactory vFactory = null;
+
+ if (className != null) {
+ try {
+ vFactory = (AuthConfigFactory)
+ Class.forName(className, true, Thread.currentThread()
+ .getContextClassLoader())
+ .getDeclaredConstructor()
+ .newInstance();
+ logger.info("Instantiated Vendor's AuthConfigFactory");
+
+ } catch (Exception e) {
+ logger.info("Error instantiating vendor's " + "AuthConfigFactory class :" + className);
+ e.printStackTrace();
+
+ }
+ }
+
+ return vFactory;
+ }
+
+ /*
+ * Read the provider configuration XML file and registers each provider with Vendor's default AuthConfigFactory
+ */
+ private Collection readProviderConfigurationXMLFile() {
+ Collection providerConfigurationEntriesCollection = null;
+
+ logger.info("Reading TestSuite Providers from :" + providerConfigFileLocation);
+ try {
+ // Given the provider configuration xml file
+ // This reader parses the xml file and stores the configuration
+ // entries as a collection.
+ configFileProcessor = new ProviderConfigurationXMLFileProcessor(providerConfigFileLocation);
+
+ // Retrieve the ProviderConfigurationEntries collection
+ providerConfigurationEntriesCollection = configFileProcessor.getProviderConfigurationEntriesCollection();
+
+ logger.info("TestSuite Providers read successfully " + "from ProviderConfiguration.xml file");
+
+ return providerConfigurationEntriesCollection;
+
+ } catch (Exception e) {
+ logger.info("Error loading Providers");
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private boolean verifyRegistrations(AuthConfigFactory acf) {
+ logger.info("Verifying Provider Registrations ...");
+
+ try {
+ // Create a Registration listener
+ RegistrationListener rlis = new TSRegistrationListener();
+
+ // Get AuthConfigProvider for soap layer
+ AuthConfigProvider acp = acf.getConfigProvider(JASPICData.LAYER_SOAP, soapAppContext, rlis);
+
+ if (acp != null) {
+ if (acp.getClass().getName().equals("com.sun.ts.tests.jaspic.tssv.config.TSAuthConfigProvider")) {
+ logger.info("TSAuthConfigProvider registered for" + " message layer=SOAP" + " and appContextId=" + soapAppContext);
+ } else {
+ logger.info("Wrong provider registerd for " + " message layer=SOAP" + " and appContextId=" + soapAppContext);
+ return false;
+
+ }
+
+ } else {
+ logger.info(
+ "Error : No AuthConfigprovider registerd for" + " message layer=SOAP" + " and appContextId=" + soapAppContext);
+ return false;
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return true;
+
+ }
+}
diff --git a/tck/spi/common/pom.xml b/tck/spi/common/pom.xml
new file mode 100644
index 0000000..456ff4d
--- /dev/null
+++ b/tck/spi/common/pom.xml
@@ -0,0 +1,46 @@
+
+
+
+ 4.0.0
+
+
+ org.eclipse.ee4j.tck.authentication
+ spi
+ 3.1.0-SNAPSHOT
+
+
+ spi.common
+
+ Jakarta Authentication TCK - Profile SPI Common
+
+ A lot of tests about the nitty gritty regarding the SPI per profile.
+
+
+
+
+ org.jakartaee
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+ jakarta.xml.ws
+ jakarta.xml.ws-api
+ 4.0.2
+
+
+
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/AuthDataCallbackHandler.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/AuthDataCallbackHandler.java
new file mode 100644
index 0000000..68ae4ea
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/AuthDataCallbackHandler.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class AuthDataCallbackHandler implements CallbackHandler {
+
+ private String user;
+ private String password;
+
+ // Default constructor gets the user and password from the environment
+ // using system property j2eelogin.name and j2eelogin.password
+ public AuthDataCallbackHandler() {
+ user = System.getProperty("j2eelogin.name");
+ password = System.getProperty("j2eelogin.password");
+ }
+
+ public AuthDataCallbackHandler(String usr, String pwd) {
+ user = usr;
+ password = pwd;
+ }
+
+ @Override
+ public void handle(Callback[] callbacks) {
+ for (Callback cb : callbacks) {
+ if (cb instanceof NameCallback) {
+ NameCallback nc = (NameCallback) cb;
+ nc.setName(user);
+ } else if (cb instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback) cb;
+ if (password != null) {
+ pc.setPassword(password.toCharArray());
+ } else {
+ pc.setPassword(null);
+ }
+ }
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/CommonCallbackSupport.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/CommonCallbackSupport.java
new file mode 100644
index 0000000..8347519
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/CommonCallbackSupport.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.callback.CertStoreCallback;
+import jakarta.security.auth.message.callback.PrivateKeyCallback;
+import jakarta.security.auth.message.callback.SecretKeyCallback;
+import jakarta.security.auth.message.callback.TrustStoreCallback;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.CertStore;
+import java.util.logging.Level;
+import javax.crypto.SecretKey;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class CommonCallbackSupport {
+ private static TSLogger logger = null;
+ private static CallbackHandler callbackHandler = null;
+ private static String profile = null;
+ private static String runtimeType = null;
+
+ public CommonCallbackSupport(TSLogger tsLogger, CallbackHandler cbkHandler, String profile, String runtimeType) {
+ logger = tsLogger;
+ callbackHandler = cbkHandler;
+ this.profile = profile;
+ this.runtimeType = runtimeType;
+ }
+
+ public boolean verify() {
+ try {
+ CertStoreCallbackSupport();
+ PrivateKeyCallbackSupport();
+ SecretKeyCallbackSupport();
+ TrustStoreCallbackSupport();
+ return true;
+
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ private void CertStoreCallbackSupport() {
+ if (callbackHandler != null) {
+ try {
+ CertStoreCallback certStoreCallback = new CertStoreCallback();
+ Callback[] callbacks = new Callback[] { certStoreCallback };
+
+ callbackHandler.handle(callbacks);
+ CertStore certStore = certStoreCallback.getCertStore();
+
+ if (certStore != null) {
+ logMsg("CertStore type =" + certStore.getType());
+ }
+ logMsg("CallbackHandler supports CertStoreCallback");
+
+ } catch (UnsupportedCallbackException usce) {
+ logMsg("CallbackHandler failed to support CertStoreCallback :" + usce.getMessage());
+ usce.printStackTrace();
+ } catch (IOException ioe) {
+ logMsg("CallbackHandler failed to support CertStoreCallback :" + ioe.getMessage());
+ ioe.printStackTrace();
+ }
+
+ }
+
+ }
+
+ private void PrivateKeyCallbackSupport() {
+ if (callbackHandler != null) {
+ try {
+
+ PrivateKeyCallback.AliasRequest aliasRequest = new PrivateKeyCallback.AliasRequest("s1as");
+
+ PrivateKeyCallback privateKeyCallback = new PrivateKeyCallback(aliasRequest);
+
+ Callback[] callbacks = new Callback[] { privateKeyCallback };
+
+ callbackHandler.handle(callbacks);
+
+ PrivateKey privateKey = privateKeyCallback.getKey();
+
+ if (privateKey != null) {
+ logMsg("Private Key for s1as =" + privateKey.getAlgorithm());
+ }
+ logMsg("CallbackHandler supports PrivateKeyCallback");
+ } catch (UnsupportedCallbackException usce) {
+ logMsg("CallbackHandler failed to support PrivateKeyCallback :" + usce.getMessage());
+ usce.printStackTrace();
+ } catch (IOException ioe) {
+ logMsg("CallbackHandler failed to support PrivateKeyCallback :" + ioe.getMessage());
+ ioe.printStackTrace();
+ }
+
+ }
+ }
+
+ private void SecretKeyCallbackSupport() {
+ if (callbackHandler != null) {
+ try {
+
+ SecretKeyCallback.AliasRequest aliasRequest = new SecretKeyCallback.AliasRequest("s1as");
+
+ SecretKeyCallback secretKeyCallback = new SecretKeyCallback(aliasRequest);
+
+ Callback[] callbacks = new Callback[] { secretKeyCallback };
+
+ callbackHandler.handle(callbacks);
+
+ SecretKey secretKey = secretKeyCallback.getKey();
+
+ if (secretKey != null) {
+ logMsg("Secret Key for s1as =" + secretKey.getAlgorithm());
+ }
+ logMsg("CallbackHandler supports SecretKeyCallback");
+ } catch (UnsupportedCallbackException usce) {
+ logMsg("CallbackHandler failed to support secretKeyCallback :" + usce.getMessage());
+ usce.printStackTrace();
+ } catch (IOException ioe) {
+ logMsg("CallbackHandler failed to support secretKeyCallback :" + ioe.getMessage());
+ ioe.printStackTrace();
+ }
+
+ }
+
+ }
+
+ private void TrustStoreCallbackSupport() {
+ if (callbackHandler != null) {
+ try {
+ TrustStoreCallback trustStoreCallback = new TrustStoreCallback();
+ Callback[] callbacks = new Callback[] { trustStoreCallback };
+
+ callbackHandler.handle(callbacks);
+ KeyStore trustStore = trustStoreCallback.getTrustStore();
+
+ if (trustStore != null) {
+ logMsg("TrustStore type =" + trustStore.getType());
+ }
+ logMsg("CallbackHandler supports TrustStoreCallback");
+ } catch (UnsupportedCallbackException usce) {
+ logMsg("CallbackHandler failed to support TrustStoreCallback :" + usce.getMessage());
+ usce.printStackTrace();
+ } catch (IOException ioe) {
+ logMsg("CallbackHandler failed to support TrustStoreCallback :" + ioe.getMessage());
+ ioe.printStackTrace();
+ }
+ }
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, "In " + profile + " : " + runtimeType + " " + str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ProviderConfigurationEntry.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ProviderConfigurationEntry.java
new file mode 100644
index 0000000..7d339a9
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ProviderConfigurationEntry.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class ProviderConfigurationEntry implements Serializable {
+
+ private static final long serialVersionUID = 249772730727896379L;
+
+ private String providerClassName;
+ private Map properties;
+ private String messageLayer;
+ private String applicationContextId;
+ private String registrationDescription;
+
+ /** Creates a new instance of ProviderConfigurationEntry */
+ public ProviderConfigurationEntry(Node providerConfigEntryNode) throws Exception {
+ Node childNode;
+ String nodeName;
+
+ // make sure the nodename is provider-config-entry
+ if (!providerConfigEntryNode.getNodeName().equals("provider-config-entry")) {
+ throw new Exception("Unexpected tag :" + providerConfigEntryNode.getNodeName());
+ }
+ NodeList nodes = providerConfigEntryNode.getChildNodes();
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+
+ childNode = nodes.item(i);
+ nodeName = childNode.getNodeName();
+
+ // Skip empty text node processing
+ if (nodeName.equals("#text"))
+ continue;
+
+ if (nodeName.equals("provider-class")) {
+ providerClassName = getText(childNode);
+
+ } else if (nodeName.equals("properties")) {
+ properties = loadProperties(childNode);
+
+ } else if (nodeName.equals("message-layer")) {
+ messageLayer = getText(childNode);
+
+ } else if (nodeName.equals("app-context-id")) {
+ applicationContextId = getText(childNode);
+
+ } else if (nodeName.equals("reg-description")) {
+ registrationDescription = getText(childNode);
+ }
+ }
+
+ }
+
+ // This method loads a given Properties node such as the one shown below
+ // and stores the values into a properties object called "properties"
+ //
+ // true
+ // USER_NAME_PASSWORD
+ //
+ private static Map loadProperties(Node node) {
+ Node topLevelChildNode = null;
+ String topLevelNodeName;
+ String key = null;
+ String value = null;
+ NamedNodeMap namedNodeMap = null;
+ Properties nodeProperties = new Properties();
+
+ NodeList nodes = node.getChildNodes();
+ for (int i = 0; i < nodes.getLength(); i++) {
+
+ topLevelChildNode = nodes.item(i);
+ topLevelNodeName = topLevelChildNode.getNodeName();
+
+ // Skip empty text node processing
+ if (topLevelNodeName.equals("#text"))
+ continue;
+
+ if (topLevelNodeName.equals("entry")) {
+ namedNodeMap = topLevelChildNode.getAttributes();
+ Node tempKeyNode = namedNodeMap.getNamedItem("key");
+ key = tempKeyNode.getNodeValue();
+ value = topLevelChildNode.getFirstChild().getNodeValue();
+ nodeProperties.put(key, value);
+ }
+ }
+
+ HashMap map = new HashMap<>();
+ nodeProperties.stringPropertyNames().forEach((tmpkey) -> map.put(tmpkey, nodeProperties.getProperty(tmpkey)));
+ return map;
+ }
+
+ public String getProviderClassName() {
+ return providerClassName;
+ }
+
+ public String getMessageLayer() {
+ return messageLayer;
+ }
+
+ public String getApplicationContextId() {
+ return applicationContextId;
+ }
+
+ public String getRegistrationDescription() {
+ return registrationDescription;
+ }
+
+ public Map getProperties() {
+ return properties;
+ }
+
+ public String getText(Node textNode) {
+ String result = "";
+ NodeList nodes = textNode.getChildNodes();
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ result = node.getNodeValue();
+ break;
+ }
+ }
+
+ if (result != null)
+ result = result.trim();
+
+ return result;
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ProviderConfigurationXMLFileProcessor.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ProviderConfigurationXMLFileProcessor.java
new file mode 100644
index 0000000..b0c6d3c
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ProviderConfigurationXMLFileProcessor.java
@@ -0,0 +1,737 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class ProviderConfigurationXMLFileProcessor {
+
+ private static Collection providerConfigurationEntriesCollection = new Vector();
+
+ private static Document document = null;
+ private static File providerConfigFile = null;
+
+ /** Creates a new instance of ProviderConfigurationXMLFileReader */
+ public ProviderConfigurationXMLFileProcessor(String fileName) throws Exception {
+
+ try {
+ providerConfigurationEntriesCollection.clear(); // XXXX:
+
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+
+ documentBuilder.setEntityResolver(new DTDResolver());
+
+ if (fileName != null)
+ providerConfigFile = new File(fileName);
+
+ if (!providerConfigFile.exists()) {
+ throw new Exception("Provider Config File : " + fileName + " does not exists");
+ } else {
+
+ FileInputStream fis = new FileInputStream(providerConfigFile);
+
+ // Parse of the content of the file into Document
+ document = documentBuilder.parse(fis);
+
+ // get the root element "provider-config"
+ Element rootElement = document.getDocumentElement();
+
+ // get the childNodes inside the rootElement
+ // The ChildNodes are instances of "provider-config-entry" elements
+ NodeList nodes = rootElement.getChildNodes();
+
+ // For each "provider-config-entry" element load all the properties
+ // and add the ProviderConfigurationEntry into the collection
+ setProviderConfigEntryCollection(nodes);
+ }
+
+ } catch (ParserConfigurationException pce) {
+ throw new Exception("PaserConfigurationException :" + pce.getMessage());
+ } catch (SAXException se) {
+ throw new Exception("SAXException :" + se.getMessage());
+ } catch (IOException ioe) {
+ throw new Exception("IOException :" + ioe.getMessage());
+
+ } catch (SecurityException se) {
+ throw new Exception("SecurityException :" + se.getMessage());
+ }
+ }
+
+ private void setProviderConfigEntryCollection(NodeList nodes) throws Exception {
+
+ Node providerConfigEntryNode;
+ NodeList providerConfigEntryNodeChildren;
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+ // Take the first node
+ providerConfigEntryNode = nodes.item(i);
+ providerConfigEntryNodeChildren = providerConfigEntryNode.getChildNodes();
+
+ // Skip empty text node processing
+ if (providerConfigEntryNode.getNodeName().equals("#text"))
+ continue;
+
+ ProviderConfigurationEntry pce = new ProviderConfigurationEntry(providerConfigEntryNode);
+ providerConfigurationEntriesCollection.add(pce);
+ }
+ }
+
+ public Collection getProviderConfigurationEntriesCollection() {
+ return providerConfigurationEntriesCollection;
+ }
+
+ // This method creates a new provider-config-entry node and adds it to the
+ // root (provider-config) element.
+ // On successful insertion of provider-config-entry this method returns true
+ public static boolean addProviderConfigEntry(String className, Map props, String messageLayer, String appContextId, String description) {
+ boolean result = false;
+
+ Node providerConfigEntry = createProviderConfigEntry(className, props, messageLayer, appContextId, description);
+
+ boolean alreadyExists = checkIfAlreadyPresent(providerConfigEntry);
+
+ // If the currentNode doesn't exists in the configuration file then
+ // add the current node
+ if (!alreadyExists) {
+
+ // get the root element "provider-config"
+ Element rootElement = document.getDocumentElement();
+ try {
+ rootElement.appendChild(providerConfigEntry);
+ updateProviderConfigurationXMLFile();
+ result = true;
+ } catch (DOMException dome) {
+ result = false;
+ }
+ }
+
+ return result;
+ }
+
+ // This method creates a new provider-config-entry node
+ //
+ public static Node createProviderConfigEntry(String className, Map props, String messageLayer, String appContextId, String description) {
+
+ Element providerConfigEntry = null;
+
+ // get the root element "provider-config"
+ Element rootElement = document.getDocumentElement();
+
+ // create provider-config-entry
+ providerConfigEntry = (Element) document.createElement("provider-config-entry");
+
+ if (className != null) {
+ // create provider-class
+ Element providerClassEntry = (Element) document.createElement("provider-class");
+ Text classNameText = document.createTextNode(className);
+ providerClassEntry.appendChild(classNameText);
+
+ // Add provider-class to provider-config-entry
+ providerConfigEntry.appendChild(providerClassEntry);
+ }
+
+ if (props != null) {
+ // create properties
+ Element propertiesNode = (Element) document.createElement("properties");
+
+ // Iterate through the map of properties(props) and add all the
+ // entries
+ Set entries = props.entrySet();
+ Iterator iterator = entries.iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ Element entryNode = (Element) document.createElement("entry");
+ entryNode.setAttribute("key", entry.getKey().toString());
+ Text keyValueText = document.createTextNode(entry.getValue().toString());
+ entryNode.appendChild(keyValueText);
+ propertiesNode.appendChild(entryNode);
+ // System.out.println(entry.getKey() + " : "
+ // + entry.getValue());
+ }
+ providerConfigEntry.appendChild(propertiesNode);
+ }
+
+ if (messageLayer != null) {
+ // create message-layer
+ Element messageLayerEntry = (Element) document.createElement("message-layer");
+ Text messageLayerText = document.createTextNode(messageLayer);
+ messageLayerEntry.appendChild(messageLayerText);
+
+ // Add message-layer to provider-config-entry
+ providerConfigEntry.appendChild(messageLayerEntry);
+ }
+
+ if (appContextId != null) {
+ // create app-context-id
+ Element appContextIdEntry = (Element) document.createElement("app-context-id");
+ Text appContextIdText = document.createTextNode(appContextId);
+ appContextIdEntry.appendChild(appContextIdText);
+
+ // Add app-context-id to provider-config-entry
+ providerConfigEntry.appendChild(appContextIdEntry);
+ }
+
+ if (description != null) {
+ // create reg-description
+ Element regDescriptionEntry = (Element) document.createElement("reg-description");
+ Text regDescriptionText = document.createTextNode(description);
+ regDescriptionEntry.appendChild(regDescriptionText);
+
+ // Add provider-class to provider-config-entry
+ providerConfigEntry.appendChild(regDescriptionEntry);
+ }
+
+ return providerConfigEntry;
+ }
+
+ // This method uses the given string (className, messageLayer,
+ // appContextId and description) and compares them with the contents of
+ // provider-config-entry nodes, if the given strings matches for a given node
+ // then that node will be deleted. This method return false if the given
+ // strings doesn't match with any of the provider-config-entry nodes.
+ public static boolean deleteProviderConfigEntry(String className, String messageLayer, String appContextId, String description) {
+ boolean result = false;
+
+ Node providerConfigEntry = createProviderConfigEntry(className, null, messageLayer, appContextId, description);
+
+ boolean alreadyExists = checkIfAlreadyPresent(providerConfigEntry);
+
+ // get the root element "provider-config"
+ Element rootElement = document.getDocumentElement();
+
+ if (alreadyExists) {
+ try {
+ rootElement.removeChild(providerConfigEntry);
+ updateProviderConfigurationXMLFile();
+ result = true;
+ } catch (DOMException dome) {
+ result = false;
+ }
+
+ }
+
+ return result;
+ }
+
+ // This method uses the given string (className, messageLayer,
+ // appContextId and description) and compares them with the contents of
+ // provider-config-entry nodes, if the all strings matches for a given node
+ // then this method returns the corresponding provider-config-entry node,
+ // if the given strings doesn't match with any of the provider-config-entry
+ // node then this method returns null
+ public static boolean checkIfAlreadyPresent(Node node) {
+
+ Node topLevelChildNode = null;
+ String topLevelNodeName;
+ boolean result = false;
+
+ // get the root element "provider-config"
+ Element rootElement = document.getDocumentElement();
+
+ NodeList nodes = rootElement.getChildNodes();
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+
+ topLevelChildNode = nodes.item(i);
+ topLevelNodeName = topLevelChildNode.getNodeName();
+
+ // Skip empty text node processing
+ if (topLevelNodeName.equals("#text"))
+ continue;
+
+ // Check whether the given node is same as the current
+ // provider-config-entry node
+ if (topLevelNodeName.equals("provider-config-entry")) {
+ topLevelChildNode.normalize();
+ node.normalize();
+
+ // printNode(topLevelChildNode, i );
+ // printNode(node, i);
+
+ if (compareNode(topLevelChildNode, node)) {
+ return true;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private static boolean compareNode(Node source, Node target) {
+
+ NodeList topLevelChildren;
+ Node childNode;
+ String nodeName;
+
+ boolean classNameMatch = false;
+ boolean propertiesMatch = true;
+ boolean messageLayerMatch = false;
+ boolean appContextIdMatch = false;
+ boolean descriptionMatch = false;
+
+ String className = null;
+ String messageLayer = null;
+ String appContextId = null;
+ Map properties = null;
+ String description = null;
+
+ String targetClassName = null;
+ String targetMessageLayer = null;
+ String targetAppContextId = null;
+ String targetDescription = null;
+
+ // get the root element "provider-config"
+
+ // Process Source node and get className, messageLayer,
+ // properties, appContextId and description values
+ topLevelChildren = source.getChildNodes();
+ for (int j = 0; j < topLevelChildren.getLength(); j++) {
+
+ childNode = topLevelChildren.item(j);
+ nodeName = childNode.getNodeName();
+
+ // Skip empty text node processing
+ if (nodeName.equals("#text"))
+ continue;
+
+ if (nodeName.equals("provider-class")) {
+ className = childNode.getFirstChild().getNodeValue().trim();
+
+ }
+ if (nodeName.equals("properties")) {
+ properties = getPropertiesMap(childNode);
+
+ } else if (nodeName.equals("message-layer")) {
+ messageLayer = childNode.getFirstChild().getNodeValue().trim();
+
+ } else if (nodeName.equals("app-context-id")) {
+ appContextId = childNode.getFirstChild().getNodeValue().trim();
+
+ } else if (nodeName.equals("reg-description")) {
+ description = childNode.getFirstChild().getNodeValue().trim();
+ }
+ }
+
+ // Process target node and get className, messageLayer,
+ // properties, appContextId and description values
+ topLevelChildren = target.getChildNodes();
+ for (int j = 0; j < topLevelChildren.getLength(); j++) {
+
+ childNode = topLevelChildren.item(j);
+ nodeName = childNode.getNodeName();
+
+ // Skip empty text node processing
+ if (nodeName.equals("#text"))
+ continue;
+
+ if (nodeName.equals("provider-class")) {
+ targetClassName = childNode.getFirstChild().getNodeValue().trim();
+
+ }
+ if (nodeName.equals("properties")) {
+ // targetProperties=getPropertiesMap(childNode);
+ // propertiesMatch = matchProperties(childNode, properties);
+
+ } else if (nodeName.equals("message-layer")) {
+ targetMessageLayer = childNode.getFirstChild().getNodeValue().trim();
+
+ } else if (nodeName.equals("app-context-id")) {
+ targetAppContextId = childNode.getFirstChild().getNodeValue().trim();
+
+ } else if (nodeName.equals("reg-description")) {
+ targetDescription = childNode.getFirstChild().getNodeValue().trim();
+ }
+ }
+
+ if (stringCompare(className, targetClassName)) {
+ classNameMatch = true;
+ }
+ if (stringCompare(messageLayer, targetMessageLayer)) {
+ messageLayerMatch = true;
+ }
+ if (stringCompare(appContextId, targetAppContextId)) {
+ appContextIdMatch = true;
+ }
+ if (stringCompare(description, targetDescription)) {
+ descriptionMatch = true;
+ }
+
+ if (classNameMatch && propertiesMatch && messageLayerMatch && appContextIdMatch && descriptionMatch) {
+ // if both node values are same then return true;
+ return true;
+ }
+
+ return false;
+ }
+
+ private static boolean stringCompare(String source, String target) {
+ boolean result = false;
+
+ if ((source == null) && (target == null)) {
+ result = true;
+ } else if ((source != null) && target != null) {
+ if (source.equals(target)) {
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ // This method reads a Properties node such as the one shown below
+ // and returns properties Map from its values
+ //
+ //
+ // true
+ // USER_NAME_PASSWORD
+ //
+ private static Map getPropertiesMap(Node node) {
+ Node topLevelChildNode = null;
+ String topLevelNodeName;
+ String key = null;
+ String value = null;
+ NamedNodeMap namedNodeMap = null;
+ Map nodeProperties = new Properties();
+
+ NodeList nodes = node.getChildNodes();
+ for (int i = 0; i < nodes.getLength(); i++) {
+
+ topLevelChildNode = nodes.item(i);
+ topLevelNodeName = topLevelChildNode.getNodeName();
+
+ // Skip empty text node processing
+ if (topLevelNodeName.equals("#text"))
+ continue;
+
+ if (topLevelNodeName.equals("entry")) {
+ namedNodeMap = topLevelChildNode.getAttributes();
+ Node tempKeyNode = namedNodeMap.getNamedItem("key");
+ key = tempKeyNode.getNodeValue();
+ value = topLevelChildNode.getFirstChild().getNodeValue();
+ nodeProperties.put(key, value);
+ }
+
+ }
+
+ return nodeProperties;
+ }
+
+ // This method reads a Properties node such as the one shown below
+ // and constructs a properties Map from its values and compares that map with
+ // the passed verifyProperties Map, if both are equal this
+ // method returns true else false
+ //
+ //
+ // true
+ // USER_NAME_PASSWORD
+ //
+ private static boolean matchProperties(Node node, Map verifyProperties) {
+ Node topLevelChildNode = null;
+ String topLevelNodeName;
+ String key = null;
+ String value = null;
+ NamedNodeMap namedNodeMap = null;
+ Map nodeProperties = new Properties();
+ boolean result = false;
+
+ NodeList nodes = node.getChildNodes();
+ for (int i = 0; i < nodes.getLength(); i++) {
+
+ topLevelChildNode = nodes.item(i);
+ topLevelNodeName = topLevelChildNode.getNodeName();
+
+ // Skip empty text node processing
+ if (topLevelNodeName.equals("#text"))
+ continue;
+
+ if (topLevelNodeName.equals("entry")) {
+ namedNodeMap = topLevelChildNode.getAttributes();
+ Node tempKeyNode = namedNodeMap.getNamedItem("key");
+ key = tempKeyNode.getNodeValue();
+ value = topLevelChildNode.getFirstChild().getNodeValue();
+ nodeProperties.put(key, value);
+ }
+
+ }
+ if (nodeProperties.equals(verifyProperties))
+ result = true;
+
+ return result;
+ }
+
+ private static void updateProviderConfigurationXMLFile() {
+
+ // Style Sheet to indent a given XML file
+ String styleSheet = ""
+ + " " + " "
+ + " " + " " + " " + " "
+ + " " + "";
+
+ try {
+
+ StreamSource styleSource = new StreamSource(new ByteArrayInputStream(styleSheet.getBytes()));
+
+ // Use a Transformer for output
+ TransformerFactory tFactory = TransformerFactory.newInstance();
+
+ // Apply transformation specified by the stylesheet to indent the
+ // generated XML file
+ Transformer transformer = tFactory.newTransformer(styleSource);
+
+ // If indentation affects performance, then we can also use
+ // simple transformation as shown below
+ // Transformer transformer = tFactory.newFtransformer();
+
+ DOMSource source = new DOMSource(document);
+
+ // Get the DOCTYPE
+ String systemValue = (new File(document.getDoctype().getSystemId())).getName();
+
+ // Delete the original ProviderConfiguration file
+ if (providerConfigFile.exists()) {
+ providerConfigFile.delete();
+ providerConfigFile.createNewFile();
+ }
+
+ FileOutputStream fos = new FileOutputStream(providerConfigFile);
+
+ // StreamResult result = new StreamResult(System.out);
+ StreamResult result = new StreamResult(fos);
+
+ // Add Doctype to the output xml file
+ transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, systemValue);
+
+ // Indent the XML file
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+
+ // set the output type as xml
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+
+ // Do identity transformation into the result stream
+ transformer.transform(source, result);
+
+ fos.close();
+
+ } catch (TransformerConfigurationException tce) {
+ // Error generated by the parser
+ System.out.println("\n** Transformer Factory error");
+ System.out.println(" " + tce.getMessage());
+
+ // Use the contained exception, if any
+ Throwable x = tce;
+ if (tce.getException() != null)
+ x = tce.getException();
+ x.printStackTrace();
+
+ } catch (TransformerException te) {
+ // Error generated by the parser
+ System.out.println("\n** Transformation error");
+ System.out.println(" " + te.getMessage());
+
+ // Use the contained exception, if any
+ Throwable x = te;
+ if (te.getException() != null)
+ x = te.getException();
+ x.printStackTrace();
+
+ } catch (IOException ioe) {
+ // I/O error
+ ioe.printStackTrace();
+ }
+
+ }
+
+ private static void printNodes(NodeList nodes) {
+
+ Node topLevelChildNode;
+ String topLevelNodeName;
+
+ int nodeCount = 1;
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+
+ topLevelChildNode = nodes.item(i);
+ topLevelNodeName = topLevelChildNode.getNodeName();
+
+ // Skip empty text node processing
+ if (topLevelNodeName.equals("#text"))
+ continue;
+
+ printNode(topLevelChildNode, nodeCount++);
+
+ }
+ }
+
+ private static void printNode(Node node, int index) {
+ Node childNode;
+ String nodeName;
+ NodeList topLevelChildren;
+
+ System.out.println(" ");
+ topLevelChildren = node.getChildNodes();
+
+ for (int j = 0; j < topLevelChildren.getLength(); j++) {
+
+ childNode = topLevelChildren.item(j);
+ nodeName = childNode.getNodeName();
+
+ // Skip empty text node processing
+ if (nodeName.equals("#text"))
+ continue;
+
+ if (nodeName.equals("provider-class")) {
+ System.out.println(index + " ) " + "provider-class = " + getText(childNode));
+
+ } else if (nodeName.equals("properties")) {
+ printProperties(childNode);
+
+ } else if (nodeName.equals("message-layer")) {
+ System.out.println(index + " ) " + "message-layer = " + getText(childNode));
+
+ } else if (nodeName.equals("app-context-id")) {
+ System.out.println(index + " ) " + "app-context-id = " + getText(childNode));
+
+ } else if (nodeName.equals("reg-description")) {
+ System.out.println(index + " ) " + "reg-description = " + getText(childNode));
+ }
+ }
+ System.out.println("-----------------");
+
+ }
+
+ // This method prints a Properties node such as the one shown below
+ //
+ //
+ // true
+ // USER_NAME_PASSWORD
+ //
+ private static void printProperties(Node node) {
+ Node topLevelChildNode = null;
+ String topLevelNodeName;
+ String key = null;
+ String value = null;
+ NamedNodeMap namedNodeMap = null;
+ Properties nodeProperties = new Properties();
+
+ NodeList nodes = node.getChildNodes();
+ for (int i = 0; i < nodes.getLength(); i++) {
+
+ topLevelChildNode = nodes.item(i);
+ topLevelNodeName = topLevelChildNode.getNodeName();
+
+ // Skip empty text node processing
+ if (topLevelNodeName.equals("#text"))
+ continue;
+
+ if (topLevelNodeName.equals("entry")) {
+ namedNodeMap = topLevelChildNode.getAttributes();
+ Node tempKeyNode = namedNodeMap.getNamedItem("key");
+ key = tempKeyNode.getNodeValue();
+ value = topLevelChildNode.getFirstChild().getNodeValue();
+ nodeProperties.put(key, value);
+ }
+ }
+
+ if ((nodeProperties != null) && (!nodeProperties.isEmpty())) {
+ nodeProperties.list(System.out);
+ } else {
+ System.out.println("No Properties to list");
+ }
+ }
+
+ private static String getText(Node textNode) {
+ String result = "";
+ NodeList nodes = textNode.getChildNodes();
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ result = node.getNodeValue();
+ break;
+ }
+ }
+ if (result != null)
+ result = result.trim();
+ return result;
+ }
+
+ public class DTDResolver implements EntityResolver {
+ public InputSource resolveEntity(String publicID, String systemId) throws SAXException {
+ String providerConfigurationFile = null;
+ String providerConfigurationFileLocation = null;
+ int indexof = 0;
+
+ // Obtain the full path for the location of ProviderConfiguration.xml file
+ // From this value identify the directory of this file using indexOf()
+ providerConfigurationFile = System.getProperty("provider.configuration.file");
+ if (providerConfigurationFile != null) {
+
+ indexof = providerConfigurationFile.indexOf("ProviderConfiguration.xml");
+ if (indexof > 0) {
+ // Get the directory location of ProviderConfiguration.xml file
+ providerConfigurationFileLocation = providerConfigurationFile.substring(0, indexof);
+ }
+
+ if (systemId.contains("provider-configuration.xsd")) {
+ // location of schema is at /lib/schemas(from ts.jte)
+ String schemaLocation = System.getProperty("schema.file.location");
+ return new InputSource(schemaLocation + File.separator + "provider-configuration.xsd");
+ }
+ }
+ // if there is no match
+ return null;
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ServerCallbackSupport.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ServerCallbackSupport.java
new file mode 100644
index 0000000..21ce839
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/ServerCallbackSupport.java
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam;
+
+import ee.jakarta.tck.authentication.test.basic.sam.util.BASE64Decoder;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.callback.CallerPrincipalCallback;
+import jakarta.security.auth.message.callback.GroupPrincipalCallback;
+import jakarta.security.auth.message.callback.PasswordValidationCallback;
+import jakarta.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class ServerCallbackSupport {
+
+ private static TSLogger logger = null;
+ private static CallbackHandler callbackHandler = null;
+ private static String profile = null;
+ private static final String runtimeType = "ServerRuntime";
+ private static MessageInfo messageInfo = null;
+ private static Subject clientSubject = null;
+ private static Subject serverSubject = null;
+
+ // user corresponds to ts.jte user property (e.g. "j2ee")
+ private static String user = System.getProperty("j2eelogin.name");
+
+ // password corresponds to ts.jte password property (e.g. "j2ee")
+ private static String passwd = System.getProperty("j2eelogin.password");
+
+ /** Creates a new instance of ServerCallbackSupport */
+ public ServerCallbackSupport(TSLogger tsLogger, CallbackHandler cbkHandler, String profile) {
+ logger = tsLogger;
+ callbackHandler = cbkHandler;
+ this.profile = profile;
+ }
+
+ public ServerCallbackSupport(TSLogger tsLogger, CallbackHandler cbkHandler, String profile, MessageInfo msgInfo, Subject clientSubj, Subject serverSubj) {
+ logger = tsLogger;
+ callbackHandler = cbkHandler;
+ this.profile = profile;
+ this.messageInfo = msgInfo;
+ this.clientSubject = clientSubj;
+ this.serverSubject = serverSubj;
+ }
+
+ public boolean verify() {
+ try {
+ CallerPrincipalCallbackSupport();
+ GroupPrincipalCallbackSupport();
+ PasswordValidationCallbackSupport();
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public boolean verifyCPCCallback() {
+ boolean bval = CallerPrincipalCallbackSupport();
+ logMsg("verifyCPCCallback returning " + Boolean.toString(bval));
+ return bval;
+ }
+
+ public boolean verifyGPCCallback() {
+ boolean bval = GroupPrincipalCallbackSupport();
+ logMsg("verifyGPCCallback returning " + Boolean.toString(bval));
+ return bval;
+ }
+
+ public boolean verifyPVCCallback() {
+ boolean bval = PasswordValidationCallbackSupport();
+ logMsg("verifyPVCCallback returning " + Boolean.toString(bval));
+ return bval;
+ }
+
+ private boolean CallerPrincipalCallbackSupport() {
+ boolean bval = false;
+ HttpServletRequest request = null;
+
+ try {
+ request = (HttpServletRequest) messageInfo.getRequestMessage();
+ } catch (Exception ex) {
+ }
+
+ if (callbackHandler != null) {
+ try {
+ // note: we should be able to have a subject that has NO
+ // principals for the case of optional authen. Which means
+ // we should not have to explicitly set the principal here.
+ // however, for the case of mandatory authen, we will want
+ // to create a CPC using a username as opposed to a null principal.
+
+ CallerPrincipalCallback callerPrincipalCallback = null;
+ if (profile.equals(JASPICData.LAYER_SERVLET)) {
+ Principal principal = null;
+ if (messageInfo != null) {
+ HttpServletRequest req = (HttpServletRequest) messageInfo.getRequestMessage();
+ String username = getServletUsername(req);
+ String principalName = getPrincipalNameFromSubject(clientSubject);
+ String nameToLog = null;
+
+ // better to call cbh with a null principal when the policy is Not
+ // mandatory
+ // and with a legitimate principal when the policy is mandatory
+ // (unless testing send-failure or send-continue - which we are
+ // not!)
+ boolean bIsMandatory = isServletAuthMandatory(messageInfo);
+ if (bIsMandatory) {
+ logMsg("CallerPrincipalCallbackSupport() Authentication mandatory");
+ if (username != null) {
+ logMsg("CallerPrincipalCallbackSupport() auth mandatory, username != null");
+ callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, username);
+ nameToLog = username;
+ } else if (principalName != null) {
+ logMsg("CallerPrincipalCallbackSupport() auth mandatory, principalName != null");
+ callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, principalName);
+ nameToLog = principalName;
+ } else {
+ logMsg("CallerPrincipalCallbackSupport() auth mandatory, username and principalName both == null");
+ }
+ } else {
+ logMsg("CallerPrincipalCallbackSupport() Authentication NOT mandatory");
+ callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, (Principal) null);
+ }
+
+ // now for some simple invocations to ensure we can call the API's
+ // these lines serve no other purpose than to validate we can
+ // invoke the api's in order to satisfy the javadoc assertions of:
+ // JSR-196:JAVADOC:32, JSR-196:JAVADOC:33, JSR-196:JAVADOC:34
+ String cpcbkName = callerPrincipalCallback.getName();
+ Principal cpcbkPrin = callerPrincipalCallback.getPrincipal();
+ Subject cpcbkSubj = callerPrincipalCallback.getSubject();
+
+ String msg = "CallerPrincipalCallback called for profile=" + profile;
+ if (request != null) {
+ String servletPath = request.getContextPath() + request.getServletPath();
+ msg += " for servletPath=" + servletPath;
+ } else {
+ msg += " messageInfo contained null request";
+ }
+ logMsg(msg);
+
+ // this helps test JASPIC:SPEC:103
+ if (clientSubject == null) {
+ msg += " subject=null";
+ } else {
+ msg += " subject=non-null";
+ }
+ msg += " principal set = " + nameToLog;
+ logMsg(msg);
+
+ } else {
+ // uses a null principal
+ callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, principal);
+ }
+ } else {
+ // should not get into here.
+ logMsg("WARNING: ServerCallbackSupport.CallerPrincipalCallbackSupport() - profile != servlet.");
+ Subject subject = new Subject();
+ callerPrincipalCallback = new CallerPrincipalCallback(subject, (Principal) null);
+ }
+
+ Callback[] callbacks = new Callback[] { callerPrincipalCallback };
+
+ callbackHandler.handle(callbacks);
+
+ logMsg("CallbackHandler supports CallerPrincipalCallback");
+ bval = true; // if here assume successful authen
+
+ } catch (UnsupportedCallbackException usce) {
+ logMsg("CallbackHandler failed to support CallerPrincipalCallback :" + usce.getMessage());
+ usce.printStackTrace();
+
+ } catch (Exception ex) {
+ // failed CPC authentication for unknown reason
+ String servletPath = "";
+ if (request != null) {
+ servletPath = request.getContextPath() + request.getServletPath();
+ } else {
+ servletPath = "WARNING: can't determine servletpath";
+ }
+ logMsg("CPC Exception failure for servletPath=" + servletPath);
+ ex.printStackTrace();
+ }
+
+ } else {
+ String msg = "CallerPrincipalCallback has a null callbackHandler";
+ msg += " profile=" + profile;
+ if (profile.equals(JASPICData.LAYER_SERVLET) && (messageInfo != null)) {
+ // HttpServletRequest request =
+ // (HttpServletRequest)messageInfo.getRequestMessage();
+ if (request != null) {
+ String servletPath = request.getContextPath() + request.getServletPath();
+ msg += " for servletPath=" + servletPath;
+ } else {
+ msg += " messageInfo contained null request";
+ }
+ logMsg(msg);
+
+ if (clientSubject == null) {
+ msg += " subject=null";
+ } else {
+ msg += " subject=non-null";
+ }
+ String principalConcatString = getPrincipalNameFromSubject(clientSubject);
+ msg += " principal set = " + principalConcatString;
+
+ }
+ logMsg(msg);
+ }
+
+ return bval;
+ }
+
+ /*
+ * This is a convenience method. It is used to help pull out the username from the request. This method will only pull
+ * out a username if there was a client side servlet request made where Basic auth was used. This will only succeed if:
+ * 1. We have a ServletRequest that was populated correctly 2. The client side used BASE64Encoder() to encode user/pwd
+ * info 3. The user/pwd info were encoded in a format similar to the the following: String authData =
+ * username+":"+password BASE64Encode.encode(authData.getBytes())
+ *
+ * This returns just the decoded username.
+ *
+ */
+ private String getServletUsername(HttpServletRequest req) {
+ String username = null;
+ String authorization = req.getHeader("authorization");
+ BASE64Decoder decoder = new BASE64Decoder();
+
+ if ((authorization != null) && (authorization.startsWith("Basic "))) {
+ try {
+ String authStr = authorization.substring(6).trim();
+ String value = new String(decoder.decodeBuffer(authStr));
+ logMsg("decoded (request) authorization string of: " + value);
+
+ // at this point value should be in the form of :
+ if (value != null) {
+ username = value.substring(0, value.indexOf(":"));
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ return username;
+ }
+
+ /*
+ * Convenience method to get our context info. (This currently only works for servlet profile since thats all we need it
+ * for at this point.)
+ *
+ */
+ private String getServletContext(MessageInfo mInfo, String profile) {
+ String sContext = "";
+ if (profile.equals(JASPICData.LAYER_SERVLET) && (mInfo != null)) {
+ HttpServletRequest req = (HttpServletRequest) mInfo.getRequestMessage();
+ if (req != null) {
+ sContext = req.getContextPath() + req.getServletPath();
+ }
+ }
+
+ logger.log(Level.INFO, "getServletContext() returning " + sContext);
+
+ return sContext;
+ }
+
+ /*
+ * This is a convenience method that is used to determine if Authentication is mandatory. Based on the answer, there are
+ * certain requirements that will need to be met wrt setting of principals.
+ */
+ private boolean isServletAuthMandatory(MessageInfo msgInfo) {
+ boolean bval = false;
+ Map map = msgInfo.getMap();
+
+ // lets pull out some context info that we can use to help uniquely
+ // identify the source of this request
+ HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage();
+
+ String servletName = request.getServletPath();
+
+ // see assertion JASPI:SPEC:306 for details on this
+ // jsr-196 states the following key must exist for servlet profile
+ String strKey = "jakarta.security.auth.message.MessagePolicy.isMandatory";
+ String msg;
+ if (map != null) {
+ String keyVal = (String) map.get(strKey);
+ msg = "isServletAuthMandatory() called with attrs: ";
+ msg += " layer=" + JASPICData.LAYER_SERVLET;
+ msg += " servletName=" + servletName;
+ msg += " key=" + strKey;
+
+ if (keyVal == null) {
+ msg += " value=NULL";
+ bval = false; // assume false if we cant determine
+ } else if (Boolean.valueOf(keyVal).booleanValue() == true) {
+ msg += " value=Valid";
+ bval = true;
+ } else {
+ // assume false
+ msg += " value=false";
+ bval = false;
+ }
+ logger.log(Level.FINE, msg);
+ } else {
+ msg = "FAILURE: No map in MessageInfo thus no key=" + strKey;
+ logger.log(Level.SEVERE, msg);
+ }
+
+ return bval;
+ }
+
+ public String getPrincipalNameFromSubject(Subject sub) {
+ Principal principal = null;
+
+ if (sub == null) {
+ return null;
+ }
+
+ String concatPrincipalName = "";
+ Set principalSet = sub.getPrincipals();
+
+ Iterator iterator = principalSet.iterator();
+ while (iterator.hasNext()) {
+ principal = (Principal) iterator.next();
+ concatPrincipalName += principal.getName();
+ }
+
+ return concatPrincipalName;
+ }
+
+ private boolean GroupPrincipalCallbackSupport() {
+ boolean bval = false;
+ ;
+ boolean isAuthMandatory = false;
+ String strServletContext = "";
+ String principalName = "";
+
+ if (callbackHandler != null) {
+ try {
+ // note: we should be able to have a subject that has NO
+ // principals for the case of optional authen. Which means
+ // we should not have to explicitly set the principal here.
+ // however, for the case of mandatory authen, we will want
+ // to create a CPC using a username as opposed to a null principal.
+
+ Subject subject = clientSubject != null? clientSubject : new Subject();
+ String strArray[] = { "Administrator" };
+ GroupPrincipalCallback groupPrincipalCallback = new GroupPrincipalCallback(subject, strArray);
+
+ CallerPrincipalCallback callerPrincipalCallback = null;
+ if (profile.equals(JASPICData.LAYER_SERVLET)) {
+ if (messageInfo != null) {
+ HttpServletRequest req = (HttpServletRequest) messageInfo.getRequestMessage();
+ String username = getServletUsername(req);
+ principalName = getPrincipalNameFromSubject(clientSubject);
+ strServletContext = req.getServletPath();
+
+ // better to call cbh with a null principal when the policy is Not
+ // mandatory
+ // and with a legitimate principal when the policy is mandatory
+ // (unless testing send-failure or send-continue - which we are
+ // not!)
+ boolean bIsMandatory = isServletAuthMandatory(messageInfo);
+ if (bIsMandatory) {
+ isAuthMandatory = true;
+ debug("GroupPrincipalCallbackSupport() Authentication mandatory");
+ if (username != null) {
+ debug("GroupPrincipalCallbackSupport() auth mandatory, username != null");
+ callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, username);
+ } else if (principalName != null) {
+ debug("GroupPrincipalCallbackSupport() auth mandatory, principalName != null");
+ callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, principalName);
+ } else {
+ logMsg("GroupPrincipalCallbackSupport() auth mandatory, username and principalName both == null");
+ }
+ } else {
+ debug("GroupPrincipalCallbackSupport() Authentication NOT mandatory");
+ callerPrincipalCallback = new CallerPrincipalCallback(subject, (Principal) null);
+ }
+ } else {
+ // uses a null principal
+ debug("GroupPrincipalCallbackSupport(): messageInfo == null, using null principal");
+ callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, (Principal) null);
+ }
+ } else {
+ // if here, we were erroneously called by non-servlet profile
+ debug("WARNING: ServerCallbackSupport.CallerPrincipalCallbackSupport() - profile != servlet.");
+ callerPrincipalCallback = new CallerPrincipalCallback(subject, (Principal) null);
+ }
+
+ Callback[] callbacks = new Callback[] { groupPrincipalCallback, callerPrincipalCallback };
+ callbackHandler.handle(callbacks);
+
+ // this string will be searched for on client side
+ String theMessage = "GroupPrincipalCallbackSupport():";
+ theMessage += " successfully called callbackHandler.handle(callbacks)";
+ theMessage += " for servlet: " + strServletContext;
+ theMessage += " with isServletAuthMandatory = " + isAuthMandatory;
+ logMsg(theMessage);
+
+ logMsg("CallbackHandler supports GroupPrincipalCallback");
+
+ bval = true; // if here assume successful authen
+
+ } catch (UnsupportedCallbackException usce) {
+ logMsg("CallbackHandler failed to support GroupPrincipalCallback :" + usce.getMessage());
+ usce.printStackTrace();
+ } catch (IOException ioe) {
+ logMsg("CallbackHandler failed to support GroupPrincipalCallback :" + ioe.getMessage());
+ ioe.printStackTrace();
+ }
+ }
+
+ return bval;
+ }
+
+ private boolean PasswordValidationCallbackSupport() {
+ boolean bval = false;
+
+ if (callbackHandler != null) {
+ try {
+ Subject subject = new Subject();
+ String username = user; // e.g. "j2ee";
+ char[] password = passwd.toCharArray(); // e.g. {'j','2','e','e'};
+
+ PasswordValidationCallback passwordValidationCallback = new PasswordValidationCallback(subject, username, password);
+
+ CallerPrincipalCallback cpc = new CallerPrincipalCallback(subject, (Principal) null);
+
+ Callback[] callbacks = new Callback[] { passwordValidationCallback, cpc };
+
+ callbackHandler.handle(callbacks);
+ Subject returnedSubject = passwordValidationCallback.getSubject();
+ boolean result = passwordValidationCallback.getResult();
+ String userName = passwordValidationCallback.getUsername();
+ char[] returnedPassword = passwordValidationCallback.getPassword();
+ passwordValidationCallback.clearPassword();
+
+ // logMsg("PasswordValidation callback returned subject
+ // ="+returnedSubject);
+ // logMsg("PasswordValidation callback returned password
+ // ="+returnedPassword);
+ logMsg("PasswordValidation callback returned result =" + result);
+ logMsg("CallbackHandler supports PasswordValidationCallback");
+
+ bval = result;
+
+ } catch (UnsupportedCallbackException usce) {
+ logMsg("CallbackHandler failed to support PasswordValidationCallback :" + usce.getMessage());
+ usce.printStackTrace();
+ } catch (IOException ioe) {
+ logMsg("CallbackHandler failed to support PasswordValidationCallback :" + ioe.getMessage());
+ ioe.printStackTrace();
+ }
+ }
+
+ return bval;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, "In " + profile + " : " + runtimeType + " " + str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+ public void debug(String str) {
+ System.out.println(str);
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/TSAuthConfigProviderServlet.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/TSAuthConfigProviderServlet.java
new file mode 100644
index 0000000..730c739
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/TSAuthConfigProviderServlet.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2007, 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam;
+
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSServerAuthConfig;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSXMLFormatter;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.AuthConfigProvider;
+import jakarta.security.auth.message.config.ClientAuthConfig;
+import jakarta.security.auth.message.config.ServerAuthConfig;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * This class is an implementation of the AuthConfigProvider for use by the servlet profile tests.
+ *
+ * @author Sun Microsystems
+ *
+ */
+public class TSAuthConfigProviderServlet implements AuthConfigProvider {
+ private static TSLogger logger;
+
+ private HashMap serverAuthConfigMap = new HashMap();
+
+ private static Map properties = null;
+
+ // This will be called when a vendor registers TSAuthConfigProviderServlet
+ public TSAuthConfigProviderServlet(Map props, AuthConfigFactory factory) {
+ properties = props;
+
+ // For self registration
+ if (factory != null) {
+ factory.registerConfigProvider(this, null, null, "TSAuthConfigProviderServlet self registration");
+ }
+
+ if (logger == null) {
+ initializeTSLogger();
+ }
+ logger.log(Level.INFO, "invoked TSAuthConfigProviderServlet() constructor(2 args)");
+ }
+
+ /**
+ * This constructor takes a TSLogger instance as a param.
+ */
+ public TSAuthConfigProviderServlet(Map props, TSLogger tsLogger, AuthConfigFactory factory) {
+ properties = props;
+
+ // For self registration
+ if (factory != null) {
+ factory.registerConfigProvider(this, null, null, "TSAuthConfigProviderServlet self registration");
+ }
+
+ if (tsLogger != null) {
+ logger = tsLogger;
+ }
+ logger.log(Level.INFO, "invoked TSAuthConfigProviderServlet() constructor(3 args)");
+ }
+
+ /**
+ * Get an instance of ClientAuthConfig from this provider.
+ *
+ *
+ * The implementation of this method returns a ClientAuthConfig instance that describes the configuration of
+ * ClientAuthModules at a given message layer, and for use in an identified application context.
+ *
+ * @param layer a String identifying the message layer for the returned ClientAuthConfig object. This argument must not
+ * be null.
+ *
+ * @param appContext a String that identifies the messaging context for the returned ClientAuthConfig object. This
+ * argument must not be null.
+ *
+ * @param handler a CallbackHandler to be passed to the ClientAuthModules encapsulated by ClientAuthContext objects
+ * derived from the returned ClientAuthConfig. This argument may be null, in which case the implementation may assign a
+ * default handler to the configuration.
+ *
+ * @return a ClientAuthConfig Object that describes the configuration of ClientAuthModules at the message layer and
+ * messaging context identified by the layer and appContext arguments. This method does not return null.
+ *
+ * @exception AuthException if this provider does not support the assignment of a default CallbackHandler to the
+ * returned ClientAuthConfig.
+ *
+ * @exception SecurityException if the caller does not have permission to retrieve the configuration.
+ *
+ * The CallbackHandler assigned to the configuration must support the Callback objects required to be supported by the
+ * profile of this specification being followed by the messaging runtime. The CallbackHandler instance must be
+ * initialized with any application context needed to process the required callbacks on behalf of the corresponding
+ * application.
+ */
+ @Override
+ public ClientAuthConfig getClientAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException {
+ logger.log(Level.INFO, "WARNING: shouldn't get into ClientAuthConfig() for servlet profile");
+
+ // shouldn't get in here for servlet profile
+ return null;
+ }
+
+ /**
+ * Get an instance of ServerAuthConfig from this provider.
+ *
+ *
+ * The implementation of this method returns a ServerAuthConfig instance that describes the configuration of
+ * ServerAuthModules at a given message layer, and for a particular application context.
+ *
+ * @param layer a String identifying the message layer for the returned ServerAuthConfig object. This argument must not
+ * be null.
+ *
+ * @param appContext a String that identifies the messaging context for the returned ServerAuthConfig object. This
+ * argument must not be null.
+ *
+ * @param handler a CallbackHandler to be passed to the ServerAuthModules encapsulated by ServerAuthContext objects
+ * derived from the returned ServerAuthConfig. This argument may be null, in which case the implementation may assign a
+ * default handler to the configuration.
+ *
+ * @return a ServerAuthConfig Object that describes the configuration of ServerAuthModules at a given message layer, and
+ * for a particular application context. This method does not return null.
+ *
+ * @exception AuthException if this provider does not support the assignment of a default CallbackHandler to the
+ * returned ServerAuthConfig.
+ *
+ * @exception SecurityException if the caller does not have permission to retrieve the configuration.
+ *
+ * The CallbackHandler assigned to the configuration must support the Callback objects required to be supported by the
+ * profile of this specification being followed by the messaging runtime. The CallbackHandler instance must be
+ * initialized with any application context needed to process the required callbacks on behalf of the corresponding
+ * application.
+ */
+ @Override
+ public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException {
+ logger.log(Level.INFO, "TSAuthConfigProviderServlet.getServerAuthConfig() called");
+
+ String logStr = "TSAuthConfigProviderServlet.getServerAuthConfig" + " : layer=" + layer + " : appContext=" + appContext;
+ logger.log(Level.INFO, logStr);
+ try {
+ if (handler == null) {
+ // this is used to help verify assertion JASPI:SPEC:71 which
+ // that we should NOT have a null cbh passed in
+ String msg = "FAILURE: layer=" + layer + " appContext=" + appContext;
+ msg += " getServerAuthConfig() received CallbackHandler=null";
+ logger.log(Level.INFO, msg);
+ } else {
+ String msg = "layer=" + layer + " appContext=" + appContext;
+ msg += " getServerAuthConfig() received CallbackHandler=non-null";
+ logger.log(Level.INFO, msg);
+ }
+
+ ServerAuthConfig serverAuthConfig = new TSServerAuthConfig(layer, appContext, handler, properties, logger);
+ serverAuthConfigMap.put(layer + appContext, serverAuthConfig);
+
+ return serverAuthConfig;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new AuthException(e.getMessage());
+ }
+ }
+
+ /**
+ * Causes a dynamic configuration provider to update its internal state such that any resulting change to its state is
+ * reflected in the corresponding authentication context configuration objects previously created by the provider within
+ * the current process context.
+ *
+ * @exception AuthException if an error occured during the refresh.
+ *
+ * @exception SecurityException if the caller does not have permission to refresh the provider.
+ */
+ @Override
+ public void refresh() {
+ }
+
+ private static void initializeTSLogger() {
+ String logFileLocation = null;
+ if (logger != null)
+ return;
+ else {
+ try {
+ logFileLocation = System.getProperty("log.file.location");
+ if (logFileLocation != null) {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ boolean appendMode = true;
+
+ // if log file already exists, just append to it
+ TSFileHandler fileHandler = new TSFileHandler(logFileLocation + "/" + JASPICData.DEFAULT_LOG_FILE, appendMode);
+ fileHandler.setFormatter(new TSXMLFormatter());
+ logger.addHandler(fileHandler);
+ } else {
+ throw new RuntimeException("log.file.location not set");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("TSLogger Initialization failed", e);
+ }
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/TSFileHandler.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/TSFileHandler.java
new file mode 100644
index 0000000..437cfff
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/TSFileHandler.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.LogRecord;
+import java.util.logging.StreamHandler;
+
+/**
+ * Simple file Handler based on java.util.logging.FileHandler
+ *
+ */
+public class TSFileHandler extends StreamHandler {
+ private MeteredStream meter;
+
+ private boolean append;
+ private int limit;
+ private int count;
+ private String pattern;
+ private File files[];
+
+ // A metered stream is a subclass of OutputStream that
+ // (a) forwards all its output to a target stream
+ // (b) keeps track of how many bytes have been written
+ private class MeteredStream extends OutputStream {
+ OutputStream out;
+
+ int written;
+
+ MeteredStream(OutputStream out, int written) {
+ this.out = out;
+ this.written = written;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ out.write(b);
+ written++;
+ }
+
+ @Override
+ public void write(byte buff[]) throws IOException {
+ out.write(buff);
+ written += buff.length;
+ }
+
+ @Override
+ public void write(byte buff[], int off, int len) throws IOException {
+ out.write(buff, off, len);
+ written += len;
+ }
+
+ @Override
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ out.close();
+ }
+ }
+
+ private void open(File fname, boolean append) throws IOException {
+ int len = 0;
+ if (append) {
+ len = (int) fname.length();
+ }
+ FileOutputStream fout = new FileOutputStream(fname.toString(), append);
+ BufferedOutputStream bout = new BufferedOutputStream(fout);
+ meter = new MeteredStream(bout, len);
+ setOutputStream(meter);
+ }
+
+ // Private method to configure a FileHandler from LogManager
+ // properties and/or default values as specified in the class
+ // javadoc.
+ private void configure() {
+ LogManager manager = LogManager.getLogManager();
+
+ String cname = getClass().getName();
+
+ pattern = "";
+ limit = 0;
+ count = 1;
+ append = true;
+ setLevel(Level.ALL);
+ setFilter(null);
+ }
+
+ /**
+ * Initialize a FileHandler to write to the given filename, with optional append.
+ *
+ * The FileHandler is configured based on LogManager properties (or their default values) except that
+ * the given pattern argument is used as the filename pattern, the file limit is set to no limit, the file count is set
+ * to one, and the append mode is set to the given append argument.
+ *
+ * There is no limit on the amount of data that may be written, so use this with care.
+ *
+ * @param pattern the name of the output file
+ * @param append specifies append mode
+ * @exception IOException if there are IO problems opening the files.
+ * @exception SecurityException if a security manager exists and if the caller does not have
+ * LoggingPermission("control").
+ * @exception IllegalArgumentException if pattern is an empty string
+ */
+ public TSFileHandler(String pattern, boolean append) throws IOException, SecurityException {
+ if (pattern.length() < 1) {
+ throw new IllegalArgumentException();
+ }
+
+ configure();
+ this.pattern = pattern;
+ this.limit = 0;
+ this.count = 1;
+ this.append = append;
+ openFiles();
+ }
+
+ // Private method to open the set of output files, based on the
+ // configured instance variables.
+ //
+ // Note: We don't lock files or rotate files based on size limit.
+ private void openFiles() throws IOException {
+ LogManager manager = LogManager.getLogManager();
+ manager.checkAccess();
+ if (count < 1) {
+ throw new IllegalArgumentException("file count = " + count);
+ }
+ if (limit < 0) {
+ limit = 0;
+ }
+
+ int unique = 0;
+
+ files = new File[count];
+ for (int i = 0; i < count; i++) {
+ files[i] = generate(pattern, i, unique);
+ }
+
+ open(files[0], true);
+
+ }
+
+ // Generate a filename from a pattern.
+ private File generate(String pattern, int generation, int unique) throws IOException {
+ File file = null;
+ String word = "";
+ int ix = 0;
+ boolean sawg = false;
+ boolean sawu = false;
+ while (ix < pattern.length()) {
+ char ch = pattern.charAt(ix);
+ ix++;
+ char ch2 = 0;
+ if (ix < pattern.length()) {
+ ch2 = Character.toLowerCase(pattern.charAt(ix));
+ }
+ if (ch == '/') {
+ if (file == null) {
+ file = new File(word);
+ } else {
+ file = new File(file, word);
+ }
+ word = "";
+ continue;
+ } else if (ch == '%') {
+ if (ch2 == 't') {
+ String tmpDir = System.getProperty("java.io.tmpdir");
+ if (tmpDir == null) {
+ tmpDir = System.getProperty("user.home");
+ }
+ file = new File(tmpDir);
+ ix++;
+ word = "";
+ continue;
+ } else if (ch2 == 'h') {
+ file = new File(System.getProperty("user.home"));
+ if (isSetUID()) {
+ // Ok, we are in a set UID program. For safety's sake
+ // we disallow attempts to open files relative to %h.
+ throw new IOException("can't use %h in set UID program");
+ }
+ ix++;
+ word = "";
+ continue;
+ } else if (ch2 == 'g') {
+ word = word + generation;
+ sawg = true;
+ ix++;
+ continue;
+ } else if (ch2 == 'u') {
+ word = word + unique;
+ sawu = true;
+ ix++;
+ continue;
+ } else if (ch2 == '%') {
+ word = word + "%";
+ ix++;
+ continue;
+ }
+ }
+ word = word + ch;
+ }
+ if (count > 1 && !sawg) {
+ word = word + "." + generation;
+ }
+ if (unique > 0 && !sawu) {
+ word = word + "." + unique;
+ }
+ if (word.length() > 0) {
+ if (file == null) {
+ file = new File(word);
+ } else {
+ file = new File(file, word);
+ }
+ }
+ return file;
+ }
+
+ /**
+ * Format and publish a LogRecord.
+ *
+ * @param record description of the log event. A null record is silently ignored and is not published
+ */
+ @Override
+ public synchronized void publish(LogRecord record) {
+ if (!isLoggable(record)) {
+ return;
+ }
+ super.publish(record);
+ super.flush();
+ flush();
+ }
+
+ /**
+ * Close all the files.
+ *
+ * @exception SecurityException if a security manager exists and if the caller does not have
+ * LoggingPermission("control").
+ */
+ @Override
+ public synchronized void close() throws SecurityException {
+ super.close();
+ }
+
+ // Private native method to check if we are in a set UID program.
+ private static native boolean isSetUID();
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/SOAPTSServerAuthConfig.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/SOAPTSServerAuthConfig.java
new file mode 100644
index 0000000..ce2c7e8
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/SOAPTSServerAuthConfig.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SERVLET;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SOAP;
+import static java.util.logging.Level.FINE;
+import static java.util.logging.Level.INFO;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.xml.soap.MimeHeaders;
+import jakarta.xml.soap.Name;
+import jakarta.xml.soap.Node;
+import jakarta.xml.soap.SOAPBody;
+import jakarta.xml.soap.SOAPElement;
+import jakarta.xml.soap.SOAPEnvelope;
+import jakarta.xml.soap.SOAPException;
+import jakarta.xml.soap.SOAPMessage;
+import jakarta.xml.soap.SOAPPart;
+import java.util.Iterator;
+import java.util.Map;
+import javax.security.auth.callback.CallbackHandler;
+
+public class SOAPTSServerAuthConfig extends TSServerAuthConfig {
+
+ protected SOAPTSServerAuthConfig(String layer, String applicationCtxt, CallbackHandler cbkHandler, Map props) {
+ super(layer, applicationCtxt, cbkHandler, props);
+ }
+
+ public SOAPTSServerAuthConfig(String layer, String applicationCtxt, CallbackHandler cbkHandler, Map props, TSLogger tsLogger) {
+ super(layer, applicationCtxt, cbkHandler, props);
+
+ if (tsLogger != null) {
+ logger = tsLogger;
+ }
+
+ String str = "TSServerAuthConfig called for layer=" + layer + " : appContext=" + applicationCtxt;
+ logger.log(INFO, str);
+ }
+
+ @Override
+ public String getAuthContextID(MessageInfo messageInfo) {
+ logger.log(INFO, "getAuthContextID called");
+ String authContextID = null;
+
+ if (messageLayer.equals(LAYER_SOAP)) {
+ authContextID = getOpName((SOAPMessage) messageInfo.getRequestMessage());
+
+ logger.log(INFO, "getAuthContextID() called for layer=" + messageLayer + " shows AuthContextId=" + authContextID);
+
+ } else if (messageLayer.equals(LAYER_SERVLET)) {
+ super.getAuthContextID(messageInfo);
+ }
+
+ return authContextID;
+ }
+
+ private String getOpName(SOAPMessage message) {
+ if (message == null) {
+ return null;
+ }
+
+ String opName = null;
+
+ // First look for a SOAPAction header.
+ // this is what .net uses to identify the operation
+ MimeHeaders headers = message.getMimeHeaders();
+ if (headers != null) {
+ String[] actions = headers.getHeader("SOAPAction");
+ if (actions != null && actions.length > 0) {
+ opName = actions[0];
+ if (opName != null && opName.equals("\"\"")) {
+ opName = null;
+ }
+ }
+ }
+
+ // If that doesn't work then we default to trying the name
+ // of the first child element of the SOAP envelope.
+ if (opName == null) {
+ Name name = getName(message);
+ if (name != null) {
+ opName = name.getLocalName();
+ }
+ }
+
+ return opName;
+ }
+
+ private Name getName(SOAPMessage message) {
+ SOAPPart soap = message.getSOAPPart();
+ if (soap == null) {
+ return null;
+ }
+
+ try {
+ SOAPEnvelope envelope = soap.getEnvelope();
+ if (envelope == null) {
+ return null;
+ }
+
+ SOAPBody body = envelope.getBody();
+ if (body == null) {
+ return null;
+ }
+
+ Iterator childElements = body.getChildElements();
+ while (childElements.hasNext()) {
+ if (childElements.next() instanceof SOAPElement soapElement) {
+ return soapElement.getElementName();
+ }
+ }
+ } catch (SOAPException se) {
+ logger.log(FINE, "WSS: Unable to get SOAP envelope", se);
+ }
+
+ return null;
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigFactory.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigFactory.java
new file mode 100644
index 0000000..11c3ede
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigFactory.java
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.SEVERE;
+
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationEntry;
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationXMLFileProcessor;
+import ee.jakarta.tck.authentication.test.basic.sam.TSAuthConfigProviderServlet;
+import ee.jakarta.tck.authentication.test.basic.sam.TSFileHandler;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSXMLFormatter;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.config.AuthConfigProvider;
+import jakarta.security.auth.message.config.RegistrationListener;
+import jakarta.security.auth.message.module.ServerAuthModule;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ *
+ * @author Raja Perumal
+ *
+ * This is an AuthConfigFactory implementation class that will get loaded by the MessageProcessingRuntime (MPR). Once
+ * this is loaded into the MPR and the the constructor is called, the constructor will call a series of methods that
+ * will ultimately be performing the assertion tests and logging results. It will be the responsibility of the client
+ * code to verify results.
+ *
+ * Important: It is very likely that the logged messages of this class are being searched for in the logfile by the
+ * client code. Because of this, refrain from changing log messages in this file.
+ *
+ */
+public class TSAuthConfigFactory extends jakarta.security.auth.message.config.AuthConfigFactory {
+
+ private static TSLogger logger = TSLogger.getTSLogger();
+
+ private static Map authConfigProviderMap = new Hashtable();
+ private static Map registrationListenerMap = new Hashtable();
+ private static Map registrationContextMap = new Hashtable();
+
+ private static ProviderConfigurationXMLFileProcessor configFileProcessor;
+
+ public TSAuthConfigFactory() {
+ // initializeTSLogger();
+ logger.log(INFO, "Initialized TSLogger");
+ readProviderConfigurationXMLFile();
+ }
+
+ /*
+ * Read the provider configuration XML file and registers each provider with TSAuthConfigFactory
+ */
+ private void readProviderConfigurationXMLFile() {
+ String providerConfigFileLocation = System.getProperty("provider.configuration.file");
+
+ if (providerConfigFileLocation == null) {
+ // looks like prop (via jvm option) is not set correctly
+ logger.log(SEVERE, "provider.configuration.file property is not properly set/specified");
+ System.out.println("provider.configuration.file property is not properly set/specified");
+ }
+
+ try {
+ // Given the provider configuration xml file
+ // This reader parses the xml file and stores the configuration
+ // entries as a collection.
+ configFileProcessor = new ProviderConfigurationXMLFileProcessor(providerConfigFileLocation);
+
+ // Retrieve the ProviderConfigurationEntries collection
+ Collection providerConfigurationEntries =
+ configFileProcessor.getProviderConfigurationEntriesCollection();
+
+
+ // Obtain each ProviderConfigurationEntry and register it with TSAuthConfigFactory
+ for (ProviderConfigurationEntry providerConfigurationEntry : providerConfigurationEntries) {
+ if (providerConfigurationEntry != null) {
+ registerConfigProvider(
+ providerConfigurationEntry.getProviderClassName(),
+ providerConfigurationEntry.getProperties(),
+ providerConfigurationEntry.getMessageLayer(),
+ providerConfigurationEntry.getApplicationContextId(),
+ providerConfigurationEntry.getRegistrationDescription());
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ if ((e.getMessage() != null) && (!e.getMessage().equals(""))) {
+ logger.log(SEVERE, e.getMessage());
+ } else {
+ logger.log(SEVERE, "Error in readProviderConfigurationXMLFile()");
+ }
+ }
+
+ }
+
+ /**
+ * Get a registered AuthConfigProvider from the factory.
+ *
+ * Get the provider of ServerAuthConfig and/or ClientAuthConfig objects registered for the identified message layer and
+ * application context.
+ *
+ * @param layer a String identifying the message layer for which the registered AuthConfigProvider is to be returned.
+ * This argument may be null.
+ *
+ * @param appContext a String that identifys the application messaging context for which the registered
+ * AuthConfigProvider is to be returned. This argument may be null.
+ *
+ * @param listener the RegistrationListener whose notify method is to be invoked if the corresponding
+ * registration is unregistered or replaced. The value of this argument may be null.
+ *
+ * @return the implementation of the AuthConfigProvider interface registered at the factory for the layer and appContext
+ * or null if no AuthConfigProvider is selected.
+ *
+ *
+ * All factories shall employ the following precedence rules to select the registered AuthConfigProvider that matches
+ * the layer and appContext arguments:
+ *
+ *
The provider that is specifically registered for both the corresponding message layer and appContext shall be
+ * selected.
+ *
if no provider is selected according to the preceding rule, the provider specifically registered for the
+ * corresponding appContext and for all message layers shall be selected.
+ *
if no provider is selected according to the preceding rules, the provider specifically registered for the
+ * corresponding message layer and for all appContexts shall be selected.
+ *
if no provider is selected according to the preceding rules, the provider registered for all message layers and
+ * for all appContexts shall be selected.
+ *
if no provider is selected according to the preceding rules, the factory shall terminate its search for a
+ * registered provider.
+ *
+ */
+ @Override
+ public AuthConfigProvider getConfigProvider(String layer, String appContext, RegistrationListener listener) {
+ AuthConfigProvider localAuthConfigProvider = null;
+
+ // Runtime calls getConfigProvider() after calling
+ // AuthConfigFactory.getFactory()
+ // So we can assume TSAuthConfigFactory.getFactory() was called indirectly
+ logger.log(INFO, "TSAuthConfigFactory.getFactory called Indirectly");
+ logger.log(INFO, "TSAuthConfigFactory.getConfigProvider called");
+ logger.log(INFO, "getConfigProvider called for Layer : " + layer + " and AppContext :" + appContext);
+
+ if (authConfigProviderMap != null) {
+ localAuthConfigProvider = (AuthConfigProvider) authConfigProviderMap.get(layer + appContext);
+
+ // check if a provider is registered for null appContextId (i.e for all
+ // appContextId)
+ if (localAuthConfigProvider == null) {
+ localAuthConfigProvider = (AuthConfigProvider) authConfigProviderMap.get(layer + "null");
+ }
+ // register the listener for AuthConfigProvider
+ if ((listener != null) && (localAuthConfigProvider != null)) {
+ registrationListenerMap.put(localAuthConfigProvider, listener);
+ }
+
+ String logMsg = "TSAuthConfigFactory.getConfigProvider returned non-null provider for";
+ logMsg += " Layer : " + layer + " and AppContext :" + appContext;
+ logger.log(INFO, logMsg);
+ return localAuthConfigProvider;
+ } else {
+ String logMsg = "TSAuthConfigFactory.getConfigProvider returned null provider for";
+ logMsg += " Layer : " + layer + " and AppContext :" + appContext;
+ logger.log(INFO, logMsg);
+ return null;
+ }
+
+ }
+
+ /**
+ * Get the the registration context for the identified registration.
+ *
+ * @param registrationID a String that identifies a provider registration at the factory
+ *
+ * @return a RegistrationContext or null. When a Non-null value is returned, it is a copy of the registration context
+ * corresponding to the registration. Null is returned when the registration identifier does not correpond to an active
+ * registration
+ */
+ @Override
+ public RegistrationContext getRegistrationContext(String registrationID) {
+ return (RegistrationContext) registrationContextMap.get(registrationID);
+ }
+
+ /**
+ * Get the registration identifiers for all registrations of the provider instance at the factory.
+ *
+ * @param provider the AuthConfigurationProvider whose registration identifiers are to be returned. This argument may be
+ * null, in which case, it indicates that the the id's of all active registration within the factory are returned.
+ *
+ * @return an array of String values where each value identifies a provider registration at the factory. This method
+ * never returns null; it returns an empty array when their are no registrations at the factory for the identified
+ * provider.
+ */
+ @Override
+ public String[] getRegistrationIDs(AuthConfigProvider provider) {
+ Vector keyMatchVector = new Vector();
+
+ if (provider != null) {
+ Set entries = authConfigProviderMap.entrySet();
+ Iterator iterator = entries.iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ // Add all the matching keys to keyMatchVector
+ if (entry.getValue().equals(provider)) {
+ keyMatchVector.add(entry.getKey());
+ }
+ }
+ } else {
+ // if provider=null then return all keys from authConfigProviderMap
+ Set authConfigProviderMapKeySet = authConfigProviderMap.keySet();
+
+ Iterator iterator = authConfigProviderMapKeySet.iterator();
+ while (iterator.hasNext()) {
+ // Add all keys to keyMatchVector
+ keyMatchVector.add(iterator.next());
+ }
+ }
+
+ // create the result string array using keyMatchVector
+ String result[] = new String[keyMatchVector.size()];
+ int index = 0;
+
+ Iterator keyMatchVectorIterator = keyMatchVector.iterator();
+
+ while (keyMatchVectorIterator.hasNext()) {
+ // populate result string array with the contents of keyMatchVector
+ result[index++] = (String) keyMatchVectorIterator.next();
+ }
+
+ return result;
+ }
+
+ /**
+ * Disassociate the listener from all the provider registrations whose layer and appContext values are matched by the
+ * corresponding arguments to this method.
+ *
+ * @param listener the RegistrationListener to be detached.
+ *
+ * @param layer a String identifying the message layer or null.
+ *
+ * @param appContext a String value identifying the application contex or null.
+ *
+ * @return an array of String values where each value identifies a provider registration from which the listener was
+ * removed. This method never returns null; it returns an empty array if the listener was not removed from any
+ * registrations.
+ *
+ * @exception SecurityException if the caller does not have permission to detach the listener from the factory.
+ *
+ */
+
+ @Override
+ public String[] detachListener(RegistrationListener listener, String layer, String appContext) {
+ String[] str = { "" };
+ return str;
+ }
+
+ /**
+ * Remove the identified provider registration from the factory and invoke any listeners associated with the removed
+ * registration.
+ *
+ * @param registrationID a String that identifies a provider registration at the factory
+ *
+ * @return true if there was a registration with the specified identifier and it was removed. Return false if the
+ * registraionID was invalid.
+ *
+ * @exception SecurityException if the caller does not have permission to unregister the provider at the factory.
+ *
+ */
+ @Override
+ public boolean removeRegistration(String registrationID) {
+ // get the corresponding ConfigProvider for registrationID
+ // and lookup any listeners associated with that provider, if so
+ // invoke notify method on them
+ registrationContextMap.remove(registrationID);
+ return (authConfigProviderMap.remove(registrationID) != null);
+ }
+
+ /**
+ * Registers within the factory, a provider of ServerAuthConfig and/or ClientAuthConfig objects for a message layer and
+ * application context identifier.
+ *
+ *
+ * At most one registration may exist within the factory for a given combination of message layer and appContext. Any
+ * pre-existing registration with identical values for layer and appContext is replaced by a subsequent registration.
+ * When replacement occurs, the registration identifier, layer, and appContext identifier remain unchanged, and the
+ * AuthConfigProvider (with initialization properties) and description are replaced.
+ *
+ *
+ * Within the lifetime of its Java process, a factory must assign unique registration identifiers to registrations, and
+ * must never assign a previously used registration identifier to a registration whose message layer and or appContext
+ * identifier differ from the previous use.
+ *
+ *
+ * Programmatic registrations performed via this method must update (according to the replacement rules described
+ * above), the persistent declarative representation of provider registrations employed by the factory constructor.
+ *
+ * @param className the fully qualified name of an AuthConfigProvider implementation class. This argument must not be
+ * null.
+ *
+ * @param properties a Map object containing the initialization properties to be passed to the provider constructor.
+ * This argument may be null. When this argument is not null, all the values and keys occuring in the Map must be of
+ * type String.
+ *
+ * @param layer a String identifying the message layer for which the provider will be registered at the factory. A null
+ * value may be passed as an argument for this parameter, in which case, the provider is registered at all layers.
+ *
+ * @param appContext a String value that may be used by a runtime to request a configuration object from this provider.
+ * A null value may be passed as an argument for this parameter, in which case, the provider is registered for all
+ * configuration ids (at the indicated layers).
+ *
+ * @param description a text String descripting the provider. this value may be null.
+ *
+ * @return a String identifier assigned by the factory to the provider registration, and that may be used to remove the
+ * registration from the provider.
+ *
+ * @exception SecurityException if the caller does not have permission to register a provider at the factory.
+ *
+ * @exception AuthException if the provider construction or registration fails.
+ */
+ @Override
+ public String registerConfigProvider(String className, Map properties, String layer, String appContext, String description) {
+ String result = null;
+ AuthConfigProvider authConfigProvider = null;
+
+ // Hashtable can't store null as key or value so change the
+ // appcontextId to be string "null" if the input value is null
+ if (appContext == null)
+ appContext = "null";
+
+ if (layer == null)
+ layer = "null";
+
+ logger.log(INFO, "registerConfigProvider() called for layer " + layer + " and appContext " + appContext);
+ try {
+ // Here we instantiate only TSAuthConfigProvider
+ // this needs to be revisited.
+ if (className.equals(TSAuthConfigProvider.class.getName())) {
+ // instantiate CTS AuthConfigProviderImpl with logger
+ authConfigProvider = new TSAuthConfigProvider(properties, null, logger);
+ } else if (className.equals(TSAuthConfigProviderServlet.class.getName())) {
+ authConfigProvider = new TSAuthConfigProviderServlet(properties, logger, null);
+ } else {
+ throw new RuntimeException("Unknown class : " + className);
+ }
+
+ RegistrationContext previousRegistrationContext = null;
+ AuthConfigProvider previousAuthConfigProvider = null;
+ previousAuthConfigProvider = (AuthConfigProvider) authConfigProviderMap.get(layer + appContext);
+ previousRegistrationContext = (RegistrationContext) registrationContextMap.get(layer + appContext);
+
+ if (previousAuthConfigProvider == null) {
+ authConfigProviderMap.put(layer + appContext, authConfigProvider);
+ registrationContextMap.put(layer + appContext, new RegistrationContextImpl(layer, appContext, description, true));
+
+ // Add new provider to the persistent store(ProviderConfiguration.xml)
+ ProviderConfigurationXMLFileProcessor.addProviderConfigEntry(className, properties, layer, appContext, description);
+
+ } else if ((previousAuthConfigProvider != null) && (previousRegistrationContext.isPersistent() == false)) {
+ authConfigProviderMap.put(layer + appContext, authConfigProvider);
+ registrationContextMap.put(layer + appContext, new RegistrationContextImpl(layer, appContext, description, true));
+
+ // Add new provider to the persistent store(ProviderConfiguration.xml)
+ ProviderConfigurationXMLFileProcessor.addProviderConfigEntry(className, properties, layer, appContext, description);
+ }
+ result = layer + appContext;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("Exception :" + e.getMessage());
+ }
+
+ return result;
+ }
+
+ /**
+ * Registers within the (in-memory) factory, a provider of ServerAuthConfig and/or ClientAuthConfig objects for a
+ * message layer and application context identifier. This method does NOT effect the factory's persistent declarative
+ * representation of provider registrations, and intended to be used by Providers to perform self-Registration.
+ *
+ *
+ * At most one registration may exist within the factory for a given combination of message layer and appContext. Any
+ * pre-existing registration with identical values for layer and appContext is replaced by a subsequent registration.
+ * When replacement occurs, the registration identifier, layer, and appContext identifier remain unchanged, and the
+ * AuthConfigProvider (with initialization properties) and description are replaced.
+ *
+ *
+ * Within the lifetime of its Java process, a factory must assign unique registration identifiers to registrations, and
+ * must never assign a previously used registration identifier to a registration whose message layer and or appContext
+ * identifier differ from the previous use.
+ *
+ * @param provider the AuthConfigProvider to be registered at the factory (or null). Calling this method with a null
+ * value for this parameter shall cause getConfigProvider to return null when it iscalled with layer and
+ * appContext values for which the resulting registration is the best match.
+ *
+ * @param layer a String identifying the message layer for which the provider will be registered at the factory. A null
+ * value may be passed as an argument for this parameter, in which case, the provider is registered at all layers.
+ *
+ * @param appContext a String value that may be used by a runtime to request a configuration object from this provider.
+ * A null value may be passed as an argument for this parameter, in which case, the provider is registered for all
+ * configuration ids (at the indicated layers).
+ *
+ * @param description a text String descripting the provider. this value may be null.
+ *
+ * @return a String identifier assigned by the factory to the provider registration, and that may be used to remove the
+ * registration from the provider.
+ *
+ * @exception SecurityException if the caller does not have permission to register a provider at the factory.
+ *
+ * @exception AuthException if the provider registration fails.
+ */
+ @Override
+ public String registerConfigProvider(AuthConfigProvider provider, String layer, String appContext, String description) {
+
+ String result = null;
+ String providerClassName = null;
+
+ logger.log(INFO, "registerConfigProvider() called for layer " + layer + " and appContext " + appContext);
+
+ if (provider == null) {
+ return result;
+ }
+
+ try {
+ RegistrationContext previousRC = null;
+ AuthConfigProvider previousACP = null;
+ previousACP = (AuthConfigProvider) authConfigProviderMap.get(layer + appContext);
+ previousRC = (RegistrationContext) registrationContextMap.get(layer + appContext);
+
+ if (previousACP == null) {
+
+ authConfigProviderMap.put(layer + appContext, provider);
+ registrationContextMap.put(layer + appContext, new RegistrationContextImpl(layer, appContext, description, false));
+
+ } else if ((previousACP != null) && (previousRC.isPersistent() == true)) {
+ // update registration context
+ registrationContextMap.put(layer + appContext, new RegistrationContextImpl(layer, appContext, description, false));
+
+ if (provider != null) {
+ providerClassName = provider.getClass().getName();
+ }
+
+ // delete existing provider from its persistent state
+ ProviderConfigurationXMLFileProcessor.deleteProviderConfigEntry(providerClassName, layer, appContext, description);
+ }
+ result = layer + appContext;
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("Exception :" + e.getMessage());
+ }
+
+ return result;
+ }
+
+ /**
+ * Registers within the (in-memory) factory, an instance of a ServerAuthModule for a message layer and
+ * application context identifier as identified by a profile specific context object.
+ *
+ *
+ * This will override any other modules that have already been registered, either via proprietary means or using the
+ * standard API. The ServerAuthModule is removed, via a call to removeServerAuthModule when
+ * the context associated with the profile specific context object ends.
+ *
+ *
+ * Note that this method is a convenience method that can be used instead of registerConfigProvider, but
+ * should ultimately have the same effect. That is, the layer and appContext parameters are
+ * generated from the context object, and the ServerAuthModule is wrapped by an implementation specific
+ * AuthConfigProvider, which are then used to call registerConfigProvider or an internal
+ * method with the same effect. The returned registration ID is then associated with the profile specific context
+ * object, and also returned from this method.
+ *
+ *
+ * A "profile specific context object" is for example the ServletContext in the Servlet Container Profile.
+ * The context associated with this ServletContext ends when for example the application corresponding to
+ * it is undeployed. Association of the registration ID with the ServletContext simply means calling the
+ * setAttribute method on the ServletContext, with the registration ID as value. (The name
+ * attribute has not been standardised in this version of the specification)
+ *
+ * @param serverAuthModule the ServerAuthModule instance to be registered
+ * @param context the profile specific context of the application for which the module is registered
+ * @return A String identifier assigned by the factory to the provider registration, and that may be used to remove the
+ * registration from the factory.
+ */
+ @Override
+ public String registerServerAuthModule(ServerAuthModule serverAuthModule, Object context) {
+ logger.log(INFO, "registerServerAuthModule() called for serverAuthModule " + serverAuthModule + " and context " + context);
+ return context.toString();
+ }
+
+ /**
+ * Remove the ServerAuthModule (and potentially encompassing wrappers/factories) that was previously
+ * registered via a call to registerServerAuthModule.
+ *
+ *
+ * Note that this method is a convenience method that can be used instead of removeRegistration, but should
+ * ultimately have the same effect. That is calling removeRegistration with the return value from
+ * registerServerAuthModule must have the same effect in that the ServerAuthModule is removed.
+ *
+ * @param context the profile specific context of the application for which the module is removed.
+ */
+ @Override
+ public void removeServerAuthModule(Object context) {
+ logger.log(INFO, "removeServerAuthModule() called for context " + context);
+ }
+
+ /**
+ * Cause the factory to reprocess its persisent declarative representation of provider registrations.
+ *
+ *
+ * A factory should only replace an existing registration when a change of provider implementation class or
+ * initialization properties has occured.
+ *
+ * @exception AuthException if an error occured during the reinitialization.
+ *
+ * @exception SecurityException if the caller does not have permission to refresh the factory.
+ */
+ @Override
+ public void refresh() {
+ }
+
+ private static void initializeTSLogger() {
+ String logFileLocation = null;
+ if (logger != null)
+ return;
+ else {
+ try {
+ logFileLocation = System.getProperty("log.file.location");
+ System.out.println("logFileLocation = " + logFileLocation);
+ if (logFileLocation != null) {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ boolean appendMode = true;
+
+ // create a new file
+ TSFileHandler fileHandler = new TSFileHandler(logFileLocation + "/" + JASPICData.DEFAULT_LOG_FILE, appendMode);
+ fileHandler.setFormatter(new TSXMLFormatter());
+ logger.addHandler(fileHandler);
+ } else {
+ throw new RuntimeException("log.file.location not set");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("TSLogger Initialization failed", e);
+ }
+ }
+ }
+
+ private String returnString(String[] array) {
+ String output = "";
+ for (int i = 0; i < array.length; i++) {
+ output += "|" + array[i];
+ }
+
+ return output;
+ }
+
+ private static class RegistrationContextImpl implements RegistrationContext {
+ private String messageLayer;
+
+ private String appContext;
+
+ private String description;
+
+ private boolean isPersistent;
+
+ private RegistrationContextImpl(String messageLayer, String appContext, String description, boolean isPersistent) {
+ this.messageLayer = messageLayer;
+ this.appContext = appContext;
+ this.description = description;
+ this.isPersistent = isPersistent;
+ }
+
+ @Override
+ public String getMessageLayer() {
+ return messageLayer;
+ }
+
+ @Override
+ public String getAppContext() {
+ return appContext;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Get the persisted status from the registration context.
+ *
+ * @return a boolean indicating whether the registration is the result of a className based registration, or an instance
+ * based (e.g. self-) registration. Only registrations performed by Class name are persistent.
+ */
+ @Override
+ public boolean isPersistent() {
+ return isPersistent;
+ }
+
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigFactoryForStandalone.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigFactoryForStandalone.java
new file mode 100644
index 0000000..34931c2
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigFactoryForStandalone.java
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.DEFAULT_LOG_FILE;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LOGGER_NAME;
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.SEVERE;
+
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationEntry;
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationXMLFileProcessor;
+import ee.jakarta.tck.authentication.test.basic.sam.TSAuthConfigProviderServlet;
+import ee.jakarta.tck.authentication.test.basic.sam.TSFileHandler;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSXMLFormatter;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.config.AuthConfigProvider;
+import jakarta.security.auth.message.config.RegistrationListener;
+import jakarta.security.auth.message.module.ServerAuthModule;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ *
+ * @author Raja Perumal
+ *
+ * This is an AuthConfigFactory implementation class that will get loaded by the MessageProcessingRuntime (MPR). Once
+ * this is loaded into the MPR and the the constructor is called, the constructor will call a series of methods that
+ * will ultimately be performing the assertion tests and logging results. It will be the responsibility of the client
+ * code to verify results.
+ *
+ * Important: It is very likely that the logged messages of this class are being searched for in the logfile by the
+ * client code. Because of this, refrain from changing log messages in this file.
+ *
+ */
+public class TSAuthConfigFactoryForStandalone extends jakarta.security.auth.message.config.AuthConfigFactory {
+
+ private static TSLogger logger = null;
+ private static Map authConfigProviderMap = new Hashtable<>();
+ private static Map registrationListenerMap = new Hashtable<>();
+ private static Map registrationContextMap = new Hashtable();
+ private static ProviderConfigurationXMLFileProcessor configFileProcessor = null;
+
+ public TSAuthConfigFactoryForStandalone() {
+ initializeTSLogger();
+ logger.log(INFO, "Initialized TSLogger");
+ readProviderConfigurationXMLFile();
+ }
+
+ /*
+ * Read the provider configuration XML file and registers each provider with TSAuthConfigFactoryForStandalone
+ */
+ private void readProviderConfigurationXMLFile() {
+ String providerConfigFileLocation = System.getProperty("provider.configuration.file");
+
+ try {
+ // Given the provider configuration xml file
+ // This reader parses the xml file and stores the configuration entries as a collection.
+ configFileProcessor = new ProviderConfigurationXMLFileProcessor(providerConfigFileLocation);
+
+ // Retrieve the ProviderConfigurationEntries collection
+ Collection providerConfigurationEntries =
+ configFileProcessor.getProviderConfigurationEntriesCollection();
+
+ // Obtain each ProviderConfigurationEntry and register it with TSAuthConfigFactoryForStandalone
+ for (ProviderConfigurationEntry providerConfigurationEntry : providerConfigurationEntries) {
+
+ if (providerConfigurationEntry != null) {
+ registerConfigProvider(
+ providerConfigurationEntry.getProviderClassName(),
+ getCleanACPProps(providerConfigurationEntry.getProperties()),
+ providerConfigurationEntry.getMessageLayer(),
+ providerConfigurationEntry.getApplicationContextId(),
+ providerConfigurationEntry.getRegistrationDescription());
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ if ((e.getMessage() != null) && (!e.getMessage().equals(""))) {
+ logger.log(SEVERE, e.getMessage());
+ } else {
+ logger.log(SEVERE, "Error in readProviderConfigurationXMLFile()");
+ }
+ }
+
+ }
+
+ /*
+ * When registering a config provider, the properties passed to the ACF.registerConfigProvider() call can ONLY contain
+ * props t hat are string types. Non-String types must NOT be passed to the registerConfigProvider() method. This method
+ * will 'clean' a Property map so that its props can be passed to the registerConfigProvider() method.
+ */
+ private Map getCleanACPProps(Map origProps) {
+ if (origProps == null) {
+ return null;
+ }
+
+ HashMap props = new HashMap<>();
+
+ // loop thru passed in props and remove anything that is
+ // not of type String since only String type Props are allowed in our
+ // calls to registerConfigProvider()
+ for (String key : origProps.keySet()) {
+ if (key != null) {
+ Object val = origProps.get(key);
+ if (val instanceof String) {
+ // we found entry that is not String so remove it
+ props.put(key, (String) val);
+ System.out.println("TSAuthConfigFactoryForStandalone: added key=" + key + " with value = " + val);
+ } else {
+ System.out.println("TSAuthConfigFactoryForStandalone: found non-string value for key=" + key);
+ }
+ }
+ }
+
+ return props;
+ }
+
+ /**
+ * Get a registered AuthConfigProvider from the factory.
+ *
+ * Get the provider of ServerAuthConfig and/or ClientAuthConfig objects registered for the identified message layer and
+ * application context.
+ *
+ * @param layer a String identifying the message layer for which the registered AuthConfigProvider is to be returned.
+ * This argument may be null.
+ *
+ * @param appContext a String that identifys the application messaging context for which the registered
+ * AuthConfigProvider is to be returned. This argument may be null.
+ *
+ * @param listener the RegistrationListener whose notify method is to be invoked if the corresponding
+ * registration is unregistered or replaced. The value of this argument may be null.
+ *
+ * @return the implementation of the AuthConfigProvider interface registered at the factory for the layer and appContext
+ * or null if no AuthConfigProvider is selected.
+ *
+ *
+ * All factories shall employ the following precedence rules to select the registered AuthConfigProvider that matches
+ * the layer and appContext arguments:
+ *
+ *
The provider that is specifically registered for both the corresponding message layer and appContext shall be
+ * selected.
+ *
if no provider is selected according to the preceding rule, the provider specifically registered for the
+ * corresponding appContext and for all message layers shall be selected.
+ *
if no provider is selected according to the preceding rules, the provider specifically registered for the
+ * corresponding message layer and for all appContexts shall be selected.
+ *
if no provider is selected according to the preceding rules, the provider registered for all message layers and
+ * for all appContexts shall be selected.
+ *
if no provider is selected according to the preceding rules, the factory shall terminate its search for a
+ * registered provider.
+ *
+ */
+ @Override
+ public AuthConfigProvider getConfigProvider(String layer, String appContext, RegistrationListener listener) {
+ AuthConfigProvider localAuthConfigProvider = null;
+
+ // Runtime calls getConfigProvider() after calling
+ // AuthConfigFactory.getFactory()
+ logger.log(INFO, "getConfigProvider called for Layer : " + layer + " and AppContext :" + appContext);
+
+ if (authConfigProviderMap != null) {
+ localAuthConfigProvider = (AuthConfigProvider) authConfigProviderMap.get(layer + appContext);
+
+ // register the listener for AuthConfigProvider
+ if ((listener != null) && (localAuthConfigProvider != null)) {
+ registrationListenerMap.put(localAuthConfigProvider, listener);
+ }
+
+ String logMsg = "getConfigProvider returned non-null provider for";
+ logMsg += " Layer : " + layer + " and AppContext :" + appContext;
+ logger.log(INFO, logMsg);
+ return localAuthConfigProvider;
+ } else {
+ String logMsg = "getConfigProvider returned null provider for";
+ logMsg += " Layer : " + layer + " and AppContext :" + appContext;
+ logger.log(INFO, logMsg);
+ return null;
+ }
+
+ }
+
+ /**
+ * Get the the registration context for the identified registration.
+ *
+ * @param registrationID a String that identifies a provider registration at the factory
+ *
+ * @return a RegistrationContext or null. When a Non-null value is returned, it is a copy of the registration context
+ * corresponding to the registration. Null is returned when the registration identifier does not correpond to an active
+ * registration
+ */
+ @Override
+ public RegistrationContext getRegistrationContext(String registrationID) {
+ return (RegistrationContext) registrationContextMap.get(registrationID);
+ }
+
+ /**
+ * Get the registration identifiers for all registrations of the provider instance at the factory.
+ *
+ * @param provider the AuthConfigurationProvider whose registration identifiers are to be returned. This argument may be
+ * null, in which case, it indicates that the the id's of all active registration within the factory are returned.
+ *
+ * @return an array of String values where each value identifies a provider registration at the factory. This method
+ * never returns null; it returns an empty array when their are no registrations at the factory for the identified
+ * provider.
+ */
+ @Override
+ public String[] getRegistrationIDs(AuthConfigProvider provider) {
+
+ Vector keyMatchVector = new Vector();
+
+ if (provider != null) {
+ Set entries = authConfigProviderMap.entrySet();
+ Iterator iterator = entries.iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ // Add all the matching keys to keyMatchVector
+ if (entry.getValue().equals(provider)) {
+ keyMatchVector.add(entry.getKey());
+ }
+ }
+ } else {
+ // if provider=null then return all keys from authConfigProviderMap
+ Set authConfigProviderMapKeySet = authConfigProviderMap.keySet();
+
+ Iterator iterator = authConfigProviderMapKeySet.iterator();
+ while (iterator.hasNext()) {
+ // Add all keys to keyMatchVector
+ keyMatchVector.add(iterator.next());
+ }
+ }
+
+ // create the result string array using keyMatchVector
+ String result[] = new String[keyMatchVector.size()];
+ int index = 0;
+
+ Iterator keyMatchVectorIterator = keyMatchVector.iterator();
+
+ while (keyMatchVectorIterator.hasNext()) {
+ // populate result string array with the contents of keyMatchVector
+ result[index++] = (String) keyMatchVectorIterator.next();
+ }
+
+ return result;
+ }
+
+ /**
+ * Disassociate the listener from all the provider registrations whose layer and appContext values are matched by the
+ * corresponding arguments to this method.
+ *
+ * @param listener the RegistrationListener to be detached.
+ *
+ * @param layer a String identifying the message layer or null.
+ *
+ * @param appContext a String value identifying the application contex or null.
+ *
+ * @return an array of String values where each value identifies a provider registration from which the listener was
+ * removed. This method never returns null; it returns an empty array if the listener was not removed from any
+ * registrations.
+ *
+ * @exception SecurityException if the caller does not have permission to detach the listener from the factory.
+ *
+ */
+ @Override
+ public String[] detachListener(RegistrationListener listener, String layer, String appContext) {
+ return null;
+ }
+
+ /**
+ * Remove the identified provider registration from the factory and invoke any listeners associated with the removed
+ * registration.
+ *
+ * @param registrationID a String that identifies a provider registration at the factory
+ *
+ * @return true if there was a registration with the specified identifier and it was removed. Return false if the
+ * registraionID was invalid.
+ *
+ * @exception SecurityException if the caller does not have permission to unregister the provider at the factory.
+ *
+ */
+ @Override
+ public boolean removeRegistration(String registrationID) {
+ // get the corresponding ConfigProvider for registrationID
+ // and lookup any listeners associated with that provider, if so
+ // invoke notify method on them
+ registrationContextMap.remove(registrationID);
+ return (authConfigProviderMap.remove(registrationID) != null);
+ }
+
+ /**
+ * Registers within the factory, a provider of ServerAuthConfig and/or ClientAuthConfig objects for a message layer and
+ * application context identifier.
+ *
+ *
+ * At most one registration may exist within the factory for a given combination of message layer and appContext. Any
+ * pre-existing registration with identical values for layer and appContext is replaced by a subsequent registration.
+ * When replacement occurs, the registration identifier, layer, and appContext identifier remain unchanged, and the
+ * AuthConfigProvider (with initialization properties) and description are replaced.
+ *
+ *
+ * Within the lifetime of its Java process, a factory must assign unique registration identifiers to registrations, and
+ * must never assign a previously used registration identifier to a registration whose message layer and or appContext
+ * identifier differ from the previous use.
+ *
+ *
+ * Programmatic registrations performed via this method must update (according to the replacement rules described
+ * above), the persistent declarative representation of provider registrations employed by the factory constructor.
+ *
+ * @param className the fully qualified name of an AuthConfigProvider implementation class. This argument must not be
+ * null.
+ *
+ * @param properties a Map object containing the initialization properties to be passed to the provider constructor.
+ * This argument may be null. When this argument is not null, all the values and keys occuring in the Map must be of
+ * type String.
+ *
+ * @param layer a String identifying the message layer for which the provider will be registered at the factory. A null
+ * value may be passed as an argument for this parameter, in which case, the provider is registered at all layers.
+ *
+ * @param appContext a String value that may be used by a runtime to request a configuration object from this provider.
+ * A null value may be passed as an argument for this parameter, in which case, the provider is registered for all
+ * configuration ids (at the indicated layers).
+ *
+ * @param description a text String descripting the provider. this value may be null.
+ *
+ * @return a String identifier assigned by the factory to the provider registration, and that may be used to remove the
+ * registration from the provider.
+ *
+ * @exception SecurityException if the caller does not have permission to register a provider at the factory.
+ *
+ * @exception AuthException if the provider construction or registration fails.
+ */
+ @Override
+ public String registerConfigProvider(String className, Map properties, String layer, String appContext, String description) {
+ String result = null;
+ AuthConfigProvider authConfigProvider = null;
+ String theClass = TSAuthConfigProviderStandalone.class.getName();
+
+ logger.log(INFO, "registerConfigProvider() called for layer " + layer + " and appContext " + appContext);
+ try {
+ // Here we instantiate only TSAuthConfigProvider
+ // this needs to be revisited.
+ if (className.equals(TSAuthConfigProvider.class.getName())) {
+ // instantiate CTS AuthConfigProviderImpl with logger
+ authConfigProvider = new TSAuthConfigProvider(properties, null, logger);
+
+ } else if (className.equals(TSAuthConfigProviderServlet.class.getName())) {
+ authConfigProvider = new TSAuthConfigProviderServlet(properties, logger, null);
+
+ } else if (className.equals(theClass)) {
+ authConfigProvider = new TSAuthConfigProviderStandalone(properties, logger, null);
+
+ } else {
+ throw new RuntimeException("Unknown class : " + className);
+ }
+
+ RegistrationContext previousRegistrationContext = null;
+ AuthConfigProvider previousAuthConfigProvider = null;
+ previousAuthConfigProvider = (AuthConfigProvider) authConfigProviderMap.get(layer + appContext);
+ previousRegistrationContext = (RegistrationContext) registrationContextMap.get(layer + appContext);
+
+ if (previousAuthConfigProvider == null) {
+ authConfigProviderMap.put(layer + appContext, authConfigProvider);
+ registrationContextMap.put(layer + appContext, new RegistrationContextImpl(layer, appContext, description, true));
+
+ // Add new provider to the persistent store(ProviderConfiguration.xml)
+ ProviderConfigurationXMLFileProcessor.addProviderConfigEntry(className, properties, layer, appContext, description);
+
+ } else if ((previousAuthConfigProvider != null) && (previousRegistrationContext.isPersistent() == false)) {
+ authConfigProviderMap.put(layer + appContext, authConfigProvider);
+ registrationContextMap.put(layer + appContext, new RegistrationContextImpl(layer, appContext, description, true));
+
+ // Add new provider to the persistent store(ProviderConfiguration.xml)
+ ProviderConfigurationXMLFileProcessor.addProviderConfigEntry(className, properties, layer, appContext, description);
+ }
+ result = layer + appContext;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("Exception :" + e.getMessage());
+ }
+ return result;
+
+ }
+
+ /**
+ * Registers within the (in-memory) factory, a provider of ServerAuthConfig and/or ClientAuthConfig objects for a
+ * message layer and application context identifier. This method does NOT effect the factory's persistent declarative
+ * representation of provider registrations, and intended to be used by Providers to perform self-Registration.
+ *
+ *
+ * At most one registration may exist within the factory for a given combination of message layer and appContext. Any
+ * pre-existing registration with identical values for layer and appContext is replaced by a subsequent registration.
+ * When replacement occurs, the registration identifier, layer, and appContext identifier remain unchanged, and the
+ * AuthConfigProvider (with initialization properties) and description are replaced.
+ *
+ *
+ * Within the lifetime of its Java process, a factory must assign unique registration identifiers to registrations, and
+ * must never assign a previously used registration identifier to a registration whose message layer and or appContext
+ * identifier differ from the previous use.
+ *
+ * @param provider the AuthConfigProvider to be registered at the factory (or null). Calling this method with a null
+ * value for this parameter shall cause getConfigProvider to return null when it iscalled with layer and
+ * appContext values for which the resulting registration is the best match.
+ *
+ * @param layer a String identifying the message layer for which the provider will be registered at the factory. A null
+ * value may be passed as an argument for this parameter, in which case, the provider is registered at all layers.
+ *
+ * @param appContext a String value that may be used by a runtime to request a configuration object from this provider.
+ * A null value may be passed as an argument for this parameter, in which case, the provider is registered for all
+ * configuration ids (at the indicated layers).
+ *
+ * @param description a text String descripting the provider. this value may be null.
+ *
+ * @return a String identifier assigned by the factory to the provider registration, and that may be used to remove the
+ * registration from the provider.
+ *
+ * @exception SecurityException if the caller does not have permission to register a provider at the factory.
+ *
+ * @exception AuthException if the provider registration fails.
+ */
+ @Override
+ public String registerConfigProvider(AuthConfigProvider provider, String layer, String appContext, String description) {
+
+ String result = null;
+ String providerClassName = null;
+
+ logger.log(INFO, "registerConfigProvider() called for layer " + layer + " and appContext " + appContext);
+
+ if (provider == null) {
+ return result;
+ }
+
+ try {
+ RegistrationContext previousRC = null;
+ AuthConfigProvider previousACP = null;
+ previousACP = (AuthConfigProvider) authConfigProviderMap.get(layer + appContext);
+ previousRC = (RegistrationContext) registrationContextMap.get(layer + appContext);
+
+ if (previousACP == null) {
+ authConfigProviderMap.put(layer + appContext, provider);
+ registrationContextMap.put(layer + appContext, new RegistrationContextImpl(layer, appContext, description, false));
+
+ } else if ((previousACP != null) && (previousRC.isPersistent() == true)) {
+ // update registration context
+ registrationContextMap.put(layer + appContext, new RegistrationContextImpl(layer, appContext, description, false));
+
+ if (provider != null) {
+ providerClassName = provider.getClass().getName();
+ }
+
+ // delete existing provider from its persistent state
+ configFileProcessor.deleteProviderConfigEntry(providerClassName, layer, appContext, description);
+ }
+ result = layer + appContext;
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("Exception :" + e.getMessage());
+ }
+
+ return result;
+ }
+
+ /**
+ * Registers within the (in-memory) factory, an instance of a ServerAuthModule for a message layer and
+ * application context identifier as identified by a profile specific context object.
+ *
+ *
+ * This will override any other modules that have already been registered, either via proprietary means or using the
+ * standard API. The ServerAuthModule is removed, via a call to removeServerAuthModule when
+ * the context associated with the profile specific context object ends.
+ *
+ *
+ * Note that this method is a convenience method that can be used instead of registerConfigProvider, but
+ * should ultimately have the same effect. That is, the layer and appContext parameters are
+ * generated from the context object, and the ServerAuthModule is wrapped by an implementation specific
+ * AuthConfigProvider, which are then used to call registerConfigProvider or an internal
+ * method with the same effect. The returned registration ID is then associated with the profile specific context
+ * object, and also returned from this method.
+ *
+ *
+ * A "profile specific context object" is for example the ServletContext in the Servlet Container Profile.
+ * The context associated with this ServletContext ends when for example the application corresponding to
+ * it is undeployed. Association of the registration ID with the ServletContext simply means calling the
+ * setAttribute method on the ServletContext, with the registration ID as value. (The name
+ * attribute has not been standardised in this version of the specification)
+ *
+ * @param serverAuthModule the ServerAuthModule instance to be registered
+ * @param context the profile specific context of the application for which the module is registered
+ * @return A String identifier assigned by the factory to the provider registration, and that may be used to remove the
+ * registration from the factory.
+ */
+ @Override
+ public String registerServerAuthModule(ServerAuthModule serverAuthModule, Object context) {
+ logger.log(INFO, "registerServerAuthModule() called for serverAuthModule " + serverAuthModule + " and context " + context);
+ return context.toString();
+ }
+
+ /**
+ * Remove the ServerAuthModule (and potentially encompassing wrappers/factories) that was previously
+ * registered via a call to registerServerAuthModule.
+ *
+ *
+ * Note that this method is a convenience method that can be used instead of removeRegistration, but should
+ * ultimately have the same effect. That is calling removeRegistration with the return value from
+ * registerServerAuthModule must have the same effect in that the ServerAuthModule is removed.
+ *
+ * @param context the profile specific context of the application for which the module is removed.
+ */
+ @Override
+ public void removeServerAuthModule(Object context) {
+ logger.log(INFO, "removeServerAuthModule() called for context " + context);
+ }
+
+ /**
+ * Cause the factory to reprocess its persisent declarative representation of provider registrations.
+ *
+ *
+ * A factory should only replace an existing registration when a change of provider implementation class or
+ * initialization properties has occured.
+ *
+ * @exception AuthException if an error occured during the reinitialization.
+ *
+ * @exception SecurityException if the caller does not have permission to refresh the factory.
+ */
+ @Override
+ public void refresh() {
+ }
+
+ private static void initializeTSLogger() {
+ String logFileLocation = null;
+ if (logger != null) {
+ return;
+ }
+
+ try {
+ logFileLocation = System.getProperty("log.file.location");
+ System.out.println("logFileLocation = " + logFileLocation);
+ if (logFileLocation == null) {
+ throw new RuntimeException("log.file.location not set");
+ }
+
+ logger = TSLogger.getTSLogger(LOGGER_NAME);
+ boolean appendMode = true;
+
+ // Create a new file
+ TSFileHandler fileHandler = new TSFileHandler(logFileLocation + "/" + DEFAULT_LOG_FILE, appendMode);
+ fileHandler.setFormatter(new TSXMLFormatter());
+ logger.addHandler(fileHandler);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("TSLogger Initialization failed", e);
+ }
+
+ }
+
+ private static class RegistrationContextImpl implements RegistrationContext {
+ private String messageLayer;
+ private String appContext;
+ private String description;
+
+ private RegistrationContextImpl(String messageLayer, String appContext, String description, boolean isPersistent) {
+ this.messageLayer = messageLayer;
+ this.appContext = appContext;
+ this.description = description;
+ }
+
+ @Override
+ public String getMessageLayer() {
+ return messageLayer;
+ }
+
+ @Override
+ public String getAppContext() {
+ return appContext;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Get the persisted status from the registration context.
+ *
+ * @return a boolean indicating whether the registration is the result of a className based registration, or an instance
+ * based (e.g. self-) registration. Only registrations performed by Class name are persistent.
+ */
+ @Override
+ public boolean isPersistent() {
+ return false;
+ }
+
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProvider.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProvider.java
new file mode 100644
index 0000000..c36386e
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProvider.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import static java.util.logging.Level.INFO;
+
+import ee.jakarta.tck.authentication.test.basic.sam.AuthDataCallbackHandler;
+import ee.jakarta.tck.authentication.test.basic.sam.TSFileHandler;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSXMLFormatter;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.ClientAuthConfig;
+import jakarta.security.auth.message.config.ServerAuthConfig;
+import java.util.HashMap;
+import java.util.Map;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSAuthConfigProvider implements jakarta.security.auth.message.config.AuthConfigProvider {
+
+ private static TSLogger logger;
+ private static Map properties;
+ private HashMap clientAuthConfigMap = new HashMap();
+ private HashMap serverAuthConfigMap = new HashMap();
+
+ // This will be called when a vendor registers TSAuthConfigProvider
+ public TSAuthConfigProvider(Map props, AuthConfigFactory factory) {
+ properties = props;
+
+ // For self registration
+ if (factory != null) {
+ factory.registerConfigProvider(this, null, null, "TSAuthConfig Provider self registration");
+ }
+
+ if (logger == null) {
+ initializeTSLogger();
+ }
+ }
+
+ // TSAuthConfigFactory invokes this constructor with TSLogger
+ public TSAuthConfigProvider(Map props, AuthConfigFactory factory, TSLogger tsLogger) {
+ properties = props;
+
+ // For self registration
+ if (factory != null) {
+ factory.registerConfigProvider(this, null, null, "TSAuthConfig Provider self registration");
+ }
+
+ if (tsLogger != null)
+ logger = tsLogger;
+
+ }
+
+ /**
+ * Get an instance of ClientAuthConfig from this provider.
+ *
+ *
+ * The implementation of this method returns a ClientAuthConfig instance that describes the configuration of
+ * ClientAuthModules at a given message layer, and for use in an identified application context.
+ *
+ * @param layer a String identifying the message layer for the returned ClientAuthConfig object. This argument must not
+ * be null.
+ *
+ * @param appContext a String that identifies the messaging context for the returned ClientAuthConfig object. This
+ * argument must not be null.
+ *
+ * @param handler a CallbackHandler to be passed to the ClientAuthModules encapsulated by ClientAuthContext objects
+ * derived from the returned ClientAuthConfig. This argument may be null, in which case the implementation may assign a
+ * default handler to the configuration.
+ *
+ * @return a ClientAuthConfig Object that describes the configuration of ClientAuthModules at the message layer and
+ * messaging context identified by the layer and appContext arguments. This method does not return null.
+ *
+ * @exception AuthException if this provider does not support the assignment of a default CallbackHandler to the
+ * returned ClientAuthConfig.
+ *
+ * @exception SecurityException if the caller does not have permission to retrieve the configuration.
+ *
+ * The CallbackHandler assigned to the configuration must support the Callback objects required to be supported by the
+ * profile of this specification being followed by the messaging runtime. The CallbackHandler instance must be
+ * initialized with any application context needed to process the required callbacks on behalf of the corresponding
+ * application.
+ */
+ @Override
+ public ClientAuthConfig getClientAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException {
+ String logStr = "TSAuthConfigProvider.getClientAuthConfig called for " + "layer=" + layer + " : " + "appContext=" + appContext;
+
+ logger.log(INFO, logStr);
+
+ try {
+ if (handler == null) {
+ // instantiate a default callback handler that gets
+ // username and password from the environment using
+ // system property j2eelogin.name j2eelogin.password
+ handler = new AuthDataCallbackHandler();
+ } else {
+ // even if we receive vendor callbackhandler replace it with our own
+ // callbackhandler for jaspic test.
+ System.out.println("Received callbackHandler =" + handler.getClass().getName());
+ handler = new AuthDataCallbackHandler();
+ }
+
+ ClientAuthConfig clientAuthConfig = new TSClientAuthConfig(layer, appContext, handler, properties, logger);
+ clientAuthConfigMap.put(layer + appContext, clientAuthConfig);
+ return clientAuthConfig;
+ } catch (Exception e) {
+ throw new AuthException(e.getMessage());
+ }
+ }
+
+ /**
+ * Get an instance of ServerAuthConfig from this provider.
+ *
+ *
+ * The implementation of this method returns a ServerAuthConfig instance that describes the configuration of
+ * ServerAuthModules at a given message layer, and for a particular application context.
+ *
+ * @param layer a String identifying the message layer for the returned ServerAuthConfig object. This argument must not
+ * be null.
+ *
+ * @param appContext a String that identifies the messaging context for the returned ServerAuthConfig object. This
+ * argument must not be null.
+ *
+ * @param handler a CallbackHandler to be passed to the ServerAuthModules encapsulated by ServerAuthContext objects
+ * derived from the returned ServerAuthConfig. This argument may be null, in which case the implementation may assign a
+ * default handler to the configuration.
+ *
+ * @return a ServerAuthConfig Object that describes the configuration of ServerAuthModules at a given message layer, and
+ * for a particular application context. This method does not return null.
+ *
+ * @exception AuthException if this provider does not support the assignment of a default CallbackHandler to the
+ * returned ServerAuthConfig.
+ *
+ * @exception SecurityException if the caller does not have permission to retrieve the configuration.
+ *
+ * The CallbackHandler assigned to the configuration must support the Callback objects required to be supported by the
+ * profile of this specification being followed by the messaging runtime. The CallbackHandler instance must be
+ * initialized with any application context needed to process the required callbacks on behalf of the corresponding
+ * application.
+ */
+ @Override
+ public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException {
+ String logStr = "TSAuthConfigProvider.getServerAuthConfig called for " + "layer=" + layer + " : " + "appContext=" + appContext;
+
+ logger.log(INFO, logStr);
+ try {
+
+ if ((!layer.equals(JASPICData.LAYER_SERVLET)) && (handler == null)) {
+ // instantiate a default callback handler that gets
+ // username and password from the environment using
+ // system property j2eelogin.name j2eelogin.password
+ handler = new AuthDataCallbackHandler();
+ } else if ((layer.equals(JASPICData.LAYER_SERVLET)) && (handler == null)) {
+ // this is used to help verify assertion JASPI:SPEC:71 which
+ // that we should NOT have a null cbh passed in
+ String msg = "FAILURE: layer=" + layer + " appContext=" + appContext;
+ msg += " getServerAuthConfig() received CallbackHandler=null";
+ logger.log(INFO, msg);
+ }
+
+ ServerAuthConfig serverAuthConfig = null;
+
+ if (JASPICData.LAYER_SOAP.equals(layer)) {
+ serverAuthConfig = new SOAPTSServerAuthConfig(layer, appContext, handler, properties, logger);
+ } else {
+ serverAuthConfig = new TSServerAuthConfig(layer, appContext, handler, properties, logger);
+ }
+
+ serverAuthConfigMap.put(layer + appContext, serverAuthConfig);
+ return serverAuthConfig;
+ } catch (Exception e) {
+ throw new AuthException(e.getMessage());
+ }
+ }
+
+ /**
+ * Causes a dynamic configuration provider to update its internal state such that any resulting change to its state is
+ * reflected in the corresponding authentication context configuration objects previously created by the provider within
+ * the current process context.
+ *
+ * @exception AuthException if an error occured during the refresh.
+ *
+ * @exception SecurityException if the caller does not have permission to refresh the provider.
+ */
+ @Override
+ public void refresh() {
+ }
+
+ private static void initializeTSLogger() {
+ String logFileLocation = null;
+ if (logger != null)
+ return;
+ else {
+ try {
+ logFileLocation = System.getProperty("log.file.location");
+ if (logFileLocation != null) {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ boolean appendMode = true;
+
+ // if log file already exists, just append to it
+ TSFileHandler fileHandler = new TSFileHandler(logFileLocation + "/" + JASPICData.DEFAULT_LOG_FILE, appendMode);
+ fileHandler.setFormatter(new TSXMLFormatter());
+ logger.addHandler(fileHandler);
+ } else {
+ throw new RuntimeException("log.file.location not set");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("TSLogger Initialization failed", e);
+ }
+ }
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProviderStandalone.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProviderStandalone.java
new file mode 100644
index 0000000..5c34273
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSAuthConfigProviderStandalone.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2007, 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import ee.jakarta.tck.authentication.test.basic.sam.TSFileHandler;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSXMLFormatter;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.ClientAuthConfig;
+import jakarta.security.auth.message.config.ServerAuthConfig;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * This class is an implementation of the AuthConfigProvider for use by the core tests. This is used to support the
+ * scenario when a profile other than Servlet/SOAP is being defined and used with Jakarta Authentication.
+ *
+ * At the time of this test creation, the 2 main supported profiles are SOAP and Servlet. But it is very possible that
+ * someone may use Jakarta Authentication to define their own profiles. For that case, we need to have something we can use for the
+ * core tests besides SOAP/Servlet tests. This is used to support that case.
+ *
+ * @author Sun Microsystems
+ */
+public class TSAuthConfigProviderStandalone implements jakarta.security.auth.message.config.AuthConfigProvider {
+
+ // this is a default string used for Persistent Registration description
+ public static String DESC_KEY = "description_key";
+
+ private static TSLogger logger;
+
+ private HashMap serverAuthConfigMap = new HashMap();
+
+ private static Map properties = null;
+
+ private String description = null;
+
+ // This will be called when a vendor registers TSAuthConfigProviderStandalone
+ public TSAuthConfigProviderStandalone(Map props, AuthConfigFactory factory) {
+ this(props, null, factory, null);
+
+ logger.log(Level.INFO, "invoked TSAuthConfigProviderStandalone() constructor(2 args)");
+ }
+
+ /**
+ * This constructor takes a TSLogger instance as a param.
+ */
+ public TSAuthConfigProviderStandalone(Map props, TSLogger tsLogger, AuthConfigFactory factory) {
+ this(props, tsLogger, factory, null);
+
+ logger.log(Level.INFO, "invoked TSAuthConfigProviderStandalone() constructor(3 args)");
+ }
+
+ /**
+ * This constructor takes a TSLogger instance as a param.
+ */
+ public TSAuthConfigProviderStandalone(Map props, TSLogger tsLogger, AuthConfigFactory factory, String description) {
+ properties = props;
+
+ // For self registration
+ if (factory != null) {
+ factory.registerConfigProvider(this, null, null, "TSAuthConfigProviderStandalone self registration");
+ }
+
+ if (tsLogger != null) {
+ this.logger = tsLogger;
+ } else {
+ initializeTSLogger();
+ }
+
+ if (description != null) {
+ // this is usually the case for in-memory registration
+ this.description = description;
+ } else {
+ // this is usually the case for persistent registration
+ this.description = getDescFromProps(props);
+ if (this.description == null) {
+ this.description = "PERSIST_DEFAULT";
+ }
+ }
+
+ logger.log(Level.INFO, "invoked TSAuthConfigProviderStandalone() constructor(4 args)");
+ }
+
+ private String getDescFromProps(Map props) {
+ String strDesc = null;
+ if (props != null) {
+ strDesc = (String) props.get(DESC_KEY);
+ }
+
+ return strDesc;
+ }
+
+ /**
+ * Get an instance of ClientAuthConfig from this provider.
+ *
+ *
+ * The implementation of this method returns a ClientAuthConfig instance that describes the configuration of
+ * ClientAuthModules at a given message layer, and for use in an identified application context.
+ *
+ * @param layer a String identifying the message layer for the returned ClientAuthConfig object. This argument must not
+ * be null.
+ *
+ * @param appContext a String that identifies the messaging context for the returned ClientAuthConfig object. This
+ * argument must not be null.
+ *
+ * @param handler a CallbackHandler to be passed to the ClientAuthModules encapsulated by ClientAuthContext objects
+ * derived from the returned ClientAuthConfig. This argument may be null, in which case the implementation may assign a
+ * default handler to the configuration.
+ *
+ * @return a ClientAuthConfig Object that describes the configuration of ClientAuthModules at the message layer and
+ * messaging context identified by the layer and appContext arguments. This method does not return null.
+ *
+ * @exception AuthException if this provider does not support the assignment of a default CallbackHandler to the
+ * returned ClientAuthConfig.
+ *
+ * @exception SecurityException if the caller does not have permission to retrieve the configuration.
+ *
+ * The CallbackHandler assigned to the configuration must support the Callback objects required to be supported by the
+ * profile of this specification being followed by the messaging runtime. The CallbackHandler instance must be
+ * initialized with any application context needed to process the required callbacks on behalf of the corresponding
+ * application.
+ */
+ @Override
+ public ClientAuthConfig getClientAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException {
+ logger.log(Level.INFO, "WARNING: shouldnt get into ClientAuthConfig() for servlet profile");
+
+ // shouldnt get in here for servlet profile
+ return null;
+ }
+
+ /**
+ * Get an instance of ServerAuthConfig from this provider.
+ *
+ *
+ * The implementation of this method returns a ServerAuthConfig instance that describes the configuration of
+ * ServerAuthModules at a given message layer, and for a particular application context.
+ *
+ * @param layer a String identifying the message layer for the returned ServerAuthConfig object. This argument must not
+ * be null.
+ *
+ * @param appContext a String that identifies the messaging context for the returned ServerAuthConfig object. This
+ * argument must not be null.
+ *
+ * @param handler a CallbackHandler to be passed to the ServerAuthModules encapsulated by ServerAuthContext objects
+ * derived from the returned ServerAuthConfig. This argument may be null, in which case the implementation may assign a
+ * default handler to the configuration.
+ *
+ * @return a ServerAuthConfig Object that describes the configuration of ServerAuthModules at a given message layer, and
+ * for a particular application context. This method does not return null.
+ *
+ * @exception AuthException if this provider does not support the assignment of a default CallbackHandler to the
+ * returned ServerAuthConfig.
+ *
+ * @exception SecurityException if the caller does not have permission to retrieve the configuration.
+ *
+ * The CallbackHandler assigned to the configuration must support the Callback objects required to be supported by the
+ * profile of this specification being followed by the messaging runtime. The CallbackHandler instance must be
+ * initialized with any application context needed to process the required callbacks on behalf of the corresponding
+ * application.
+ */
+ @Override
+ public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException {
+ logger.log(Level.INFO, "TSAuthConfigProviderStandalone.getServerAuthConfig() called");
+
+ String logStr = "TSAuthConfigProviderStandalone.getServerAuthConfig" + " : layer=" + layer + " : appContext=" + appContext;
+ logger.log(Level.INFO, logStr);
+ try {
+ if (handler == null) {
+ // this is used to help verify assertion JASPI:SPEC:71 which
+ // that we should NOT have a null cbh passed in
+ String msg = "FAILURE: layer=" + layer + " appContext=" + appContext;
+ msg += " getServerAuthConfig() received CallbackHandler=null";
+ logger.log(Level.INFO, msg);
+ } else {
+ String msg = "layer=" + layer + " appContext=" + appContext;
+ msg += " getServerAuthConfig() received CallbackHandler=non-null";
+ logger.log(Level.INFO, msg);
+ }
+
+ ServerAuthConfig serverAuthConfig = new TSServerAuthConfig(layer, appContext, handler, properties, logger);
+ serverAuthConfigMap.put(layer + appContext, serverAuthConfig);
+
+ return serverAuthConfig;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new AuthException(e.getMessage());
+ }
+ }
+
+ /**
+ * Causes a dynamic configuration provider to update its internal state such that any resulting change to its state is
+ * reflected in the corresponding authentication context configuration objects previously created by the provider within
+ * the current process context.
+ *
+ * @exception AuthException if an error occured during the refresh.
+ *
+ * @exception SecurityException if the caller does not have permission to refresh the provider.
+ */
+ @Override
+ public void refresh() {
+ }
+
+ private static void initializeTSLogger() {
+ String logFileLocation = null;
+ if (logger != null)
+ return;
+ else {
+ try {
+ logFileLocation = System.getProperty("log.file.location");
+ if (logFileLocation != null) {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ boolean appendMode = true;
+
+ // if log file already exists, just append to it
+ TSFileHandler fileHandler = new TSFileHandler(logFileLocation + "/" + JASPICData.DEFAULT_LOG_FILE, appendMode);
+ fileHandler.setFormatter(new TSXMLFormatter());
+ logger.addHandler(fileHandler);
+ } else {
+ throw new RuntimeException("log.file.location not set");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("TSLogger Initialization failed", e);
+ }
+ }
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String val) {
+ description = val;
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthConfig.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthConfig.java
new file mode 100644
index 0000000..46d4c6b
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthConfig.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.config.ClientAuthContext;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.xml.soap.MimeHeaders;
+import jakarta.xml.soap.Name;
+import jakarta.xml.soap.SOAPBody;
+import jakarta.xml.soap.SOAPElement;
+import jakarta.xml.soap.SOAPEnvelope;
+import jakarta.xml.soap.SOAPException;
+import jakarta.xml.soap.SOAPMessage;
+import jakarta.xml.soap.SOAPPart;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSClientAuthConfig implements jakarta.security.auth.message.config.ClientAuthConfig {
+
+ private static String messageLayer;
+ private static String appContext;
+ private static CallbackHandler callbackHandler;
+ private static TSLogger logger;
+
+ private Map properties = null;
+
+ /**
+ * Creates a new instance of ClientAuthConfigImpl
+ */
+ public TSClientAuthConfig(String layer, String applicationCtxt, CallbackHandler cbkHandler, Map props) {
+ messageLayer = layer;
+ appContext = applicationCtxt;
+ callbackHandler = cbkHandler;
+ properties = props;
+ }
+
+ public TSClientAuthConfig(String layer, String applicationCtxt, CallbackHandler cbkHandler, Map props, TSLogger tsLogger) {
+ this(layer, applicationCtxt, cbkHandler, props);
+ logger = tsLogger;
+ String str = "TSClientAuthConfig called for layer=" + layer + " : appContext=" + applicationCtxt;
+ logger.log(Level.INFO, str);
+ }
+
+ /**
+ * Get the authentication context identifier corresponding to the request and response objects encapsulated in
+ * messageInfo.
+ *
+ * @param messageInfo a contextual Object that encapsulates the client request and server response objects.
+ *
+ * @return the operation identifier related to the encapsulated request and response objects, or null.
+ *
+ * @throws IllegalArgumentException if the type of the message objects incorporated in messageInfo are not compatible
+ * with the message types supported by this authentication context configuration object.
+ */
+ @Override
+ public String getAuthContextID(MessageInfo messageInfo) {
+ String rval = null;
+ logger.log(Level.INFO, "TSClientAuthConfig.getOperation called");
+ if (messageLayer.equals(JASPICData.LAYER_SOAP)) {
+
+ return getOpName((SOAPMessage) messageInfo.getRequestMessage());
+
+ } else if (messageLayer.equals(JASPICData.LAYER_SERVLET)) {
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ rval = request.getServletPath() + " " + request.getMethod();
+ return rval;
+ } else
+ return null;
+ }
+
+ private String getOpName(SOAPMessage message) {
+ if (message == null) {
+ return null;
+ }
+
+ String rvalue = null;
+
+ // first look for a SOAPAction header.
+ // this is what .net uses to identify the operation
+ MimeHeaders headers = message.getMimeHeaders();
+ if (headers != null) {
+ String[] actions = headers.getHeader("SOAPAction");
+ if (actions != null && actions.length > 0) {
+ rvalue = actions[0];
+ if (rvalue != null && rvalue.equals("\"\"")) {
+ rvalue = null;
+ }
+ }
+ }
+
+ // if that doesn't work then we default to trying the name
+ // of the first child element of the SOAP envelope.
+ if (rvalue == null) {
+ Name name = getName(message);
+ if (name != null) {
+ rvalue = name.getLocalName();
+ }
+ }
+
+ return rvalue;
+ }
+
+ private Name getName(SOAPMessage message) {
+ Name rvalue = null;
+ SOAPPart soap = message.getSOAPPart();
+ if (soap != null) {
+ try {
+ SOAPEnvelope envelope = soap.getEnvelope();
+ if (envelope != null) {
+ SOAPBody body = envelope.getBody();
+ if (body != null) {
+ Iterator> it = body.getChildElements();
+ while (it.hasNext()) {
+ Object o = it.next();
+ if (o instanceof SOAPElement) {
+ rvalue = ((SOAPElement) o).getElementName();
+ break;
+ }
+ }
+ }
+ }
+ } catch (SOAPException se) {
+ logger.log(Level.INFO, "WSS: Unable to get SOAP envelope");
+ }
+ }
+
+ return rvalue;
+ }
+
+ /**
+ * Causes a dynamic anthentication context configuration object to update the internal state that it uses to process
+ * calls to its getAuthContext method.
+ *
+ * @exception AuthException if an error occured during the update.
+ *
+ * @exception SecurityException if the caller does not have permission to refresh the configuration object.
+ */
+ @Override
+ public void refresh() {
+
+ }
+
+ /**
+ * Get the message layer name of this authentication context configuration object.
+ *
+ * @return the message layer name of this configuration object, or null if the configuration object pertains to an
+ * unspecified message layer.
+ */
+ @Override
+ public String getMessageLayer() {
+ return messageLayer;
+ }
+
+ /**
+ * Get the application context identifier of this authentication context configuration object.
+ *
+ * @return the String identifying the application context of this configuration object or null if the configuration
+ * object pertains to an unspecified application context.
+ */
+ @Override
+ public String getAppContext() {
+ return appContext;
+ }
+
+ /**
+ * Get a ClientAuthContext instance from this ClientAuthConfig.
+ *
+ *
+ * The implementation of this method returns a ClientAuthContext instance that encapsulates the ClientAuthModules used
+ * to secure and validate requests/responses associated with the given operation.
+ *
+ *
+ * Specifically, this method accesses this ClientAuthConfig object with the argument operation to determine the
+ * ClientAuthModules that are to be encapsulated in the returned ClientAuthContext instance.
+ *
+ *
+ * The ClientAuthConfig object establishes the request and response MessagePolicy objects that are passed to the
+ * encapsulated modules when they are initialized by the returned ClientAuthContext instance. It is the modules'
+ * responsibility to enforce these policies when invoked.
+ *
+ * @param operation an operation identifier used to index the provided config, or null. This value must be
+ * identical to the value returned by the getOperation method for all MessageInfo objects
+ * passed to the secureRequest method of the returned ClientAuthContext.
+ *
+ * @param clientSubject a Subject that represents the source of the service request to be secured by the acquired
+ * authentication context. The principal and/or credentials of the Subject may be used to select or acquire the
+ * authentication context. If the Subject is not null, additional Principals or credentials (pertaining to the source of
+ * the request) may be added to the Subject. A null value may be passed to for this parameter.
+ *
+ * @param properties a Map object that may be used by the caller to augment the properties that will be passed to the
+ * encapsulated modules at module initialization. The null value may be passed for this parameter.
+ *
+ * @return a ClientAuthContext instance that encapsulates the ClientAuthModules used to secure and validate
+ * requests/responses associated with the given operation, or null (indicating that no modules are configured).
+ *
+ * @exception AuthException if this operation fails.
+ */
+ @Override
+ public ClientAuthContext getAuthContext(String operation, Subject clientSubject, Map properties) throws AuthException {
+
+ // Copy properties that are passed in this method to this.properties
+ //
+ // Note: this.properties is obtained from the Provider which gets those
+ // properties during provider registration time from the factory.
+ this.properties.putAll(properties);
+
+ try {
+
+ String logStr = "TSClientAuthConfig.getAuthContext: layer=" + messageLayer + " : appContext=" + appContext;
+ logger.log(Level.INFO, logStr);
+
+ logger.log(Level.INFO, "TSClientAuthConfig.getAuthContext: layer=" + messageLayer + " : appContext=" + appContext
+ + " operationId=" + operation);
+
+ ClientAuthContext clientAuthContext = new TSClientAuthContext(messageLayer, appContext, callbackHandler, operation,
+ clientSubject, this.properties, logger);
+
+ logStr = "TSClientAuthConfig.getAuthContext: returned non-null" + " ClientAuthContext for operationId=" + operation;
+ logger.log(Level.INFO, logStr);
+ return clientAuthContext;
+ } catch (Exception e) {
+ throw new AuthException(e.getMessage());
+ }
+
+ }
+
+ /**
+ * Used to determine whether the authentication context configuration object encapsulates any protected authentication
+ * contexts.
+ *
+ * @return true if the configuration object encapsulates at least one protected authentication context. Otherwise, this
+ * method returns false.
+ */
+ @Override
+ public boolean isProtected() {
+ // To verify protected code path, always return true.
+ return true;
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthContext.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthContext.java
new file mode 100644
index 0000000..db66f38
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSClientAuthContext.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SERVLET;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SOAP;
+import static java.util.logging.Level.INFO;
+
+import ee.jakarta.tck.authentication.test.basic.sam.module.servlet.TSClientAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSAuthExceptionClientAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSFailureClientAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSSendFailureClientAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSSendSuccessClientAuthModule;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.module.ClientAuthModule;
+import java.util.Map;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSClientAuthContext implements jakarta.security.auth.message.config.ClientAuthContext {
+
+ private static ClientAuthModule clientAuthModule;
+ private static TSLogger logger;
+
+ public TSClientAuthContext() {
+
+ }
+
+ public TSClientAuthContext(String messageLayer, String appContext, CallbackHandler handler, String operation, Subject clientSubject,
+ Map properties, TSLogger tsLogger) throws AuthException {
+
+ this(messageLayer, appContext, handler, operation, clientSubject, properties);
+
+ logger = tsLogger;
+ ClientAuthModule cam = null;
+ logger.log(INFO, "TSClientAuthContext called");
+
+ // Pass TSlogger to TSServerAuthModule through properties
+ properties.put("TSLogger", logger);
+
+ if (messageLayer.equals(LAYER_SOAP)) {
+ if (appContext.indexOf("SendSuccessHello") > -1) {
+ cam = new TSSendSuccessClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("SendFailureHello") > -1) {
+ cam = new TSSendFailureClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("FailureHello") > -1) {
+ cam = new TSFailureClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("AuthExceptionHello") > -1) {
+ cam = new TSAuthExceptionClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+
+ } else {
+ cam = new ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+ }
+ } else if (messageLayer.equals(LAYER_SERVLET)) {
+ cam = new TSClientAuthModule();
+ cam.initialize(null, null, handler, properties);
+ }
+
+ clientAuthModule = cam;
+ }
+
+ private TSClientAuthContext(String layer, String appContxt, CallbackHandler hndler, String operatn, Subject cliSubject, Map props) throws AuthException {
+
+ }
+
+ /**
+ * Secure a service request message before sending it to the service.
+ *
+ * This method is called to transform the request message acquired by calling getRequestMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to secure the request. If the Subject is
+ * not null, the method implementation may add additional Principals or credentials (pertaining to the source of the
+ * service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully secured. The secured request message may
+ * be obtained by calling by getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application request message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response from the peer security system. This status value
+ * also indicates that the application message has not yet been secured.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange after having received the security-specific response elicited by sending the security message.
+ *
+ * When this status value is returned, the corresponding invocation of validateResponse must be able to
+ * obtain the original application request message.
+ *
+ *
AuthStatus.FAILURE to indicate that a failure occured while securing the request message, and that an appropriate
+ * failure response message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
+ logger.log(INFO, "TSClientAuthContext.secureRequest called");
+
+ return clientAuthModule.secureRequest(messageInfo, clientSubject);
+ }
+
+ /**
+ * Validate a received service response.
+ *
+ * This method is called to transform the mechanism specific response message acquired by calling getResponseMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the response
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into the next mechanism specific request message to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the recipient of the service response, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the response. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application response message was successfully validated. The validated message is
+ * available by calling getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that response validation is incomplete, and that a continuation request was
+ * returned as the request message within messageInfo.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange.
+ *
+ *
AuthStatus.FAILURE to indicate that validation of the response failed, and that a failure response message has
+ * been established in messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ logger.log(INFO, "TSClientAuthContext.validateResponse called");
+
+ return clientAuthModule.validateResponse(messageInfo, clientSubject, serviceSubject);
+ }
+
+ /**
+ * Remove implementation specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ clientAuthModule.cleanSubject(messageInfo, subject);
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSRegistrationListener.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSRegistrationListener.java
new file mode 100644
index 0000000..229aeda
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSRegistrationListener.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.RegistrationListener;
+
+public class TSRegistrationListener implements RegistrationListener {
+
+ String profileLayer;
+ String appContext;
+ boolean notified = false;
+ AuthConfigFactory acf = null;
+
+ public TSRegistrationListener() {
+ this.profileLayer = null;
+ this.appContext = null;
+ acf = AuthConfigFactory.getFactory();
+ }
+
+ public TSRegistrationListener(String profileLayer, String appContext) {
+ this.profileLayer = profileLayer;
+ this.appContext = appContext;
+ acf = AuthConfigFactory.getFactory();
+ }
+
+ public String getProfileLayer() {
+ return this.profileLayer;
+ }
+
+ public void setProfileLayer(String val) {
+ this.profileLayer = val;
+ }
+
+ public String getAppContext() {
+ return this.appContext;
+ }
+
+ public void setAppContext(String val) {
+ this.appContext = val;
+ }
+
+ public void resetNotifyFlag() {
+ notified = false;
+ }
+
+ public boolean notified() {
+ return notified;
+ }
+
+ /*
+ * check if notifications should occur by verifying if our actual notification (ie wasNotified) matches with our
+ * expected notification (ie notified()) return true on success and false otherwise.
+ */
+ public boolean check(String layer, String context) {
+ boolean match = false;
+ boolean rval = true;
+
+ if ((layer == null || ((profileLayer != null) && profileLayer.equals(layer)))
+ && (context == null || ((appContext != null) && appContext.equals(context)))) {
+ match = true;
+ }
+
+ String msg = "TSRegistrationListener: layer=" + profileLayer + ", appcontext=";
+ msg += appContext + " ExpectedVal=" + notified() + " actualVal=" + match + "for layer=" + layer + " context=" + context;
+
+ if (match && notified()) {
+ // should have been notification - which matches whats in notified()
+ rval = true;
+ } else if (match && !notified()) {
+ rval = false;
+ debug("in check(): " + msg);
+ }
+
+ return rval;
+ }
+
+ /*
+ * Notify the listener that a registration with which it was associated was replaced or unregistered.
+ */
+ @Override
+ public void notify(String layer, String context) {
+ notified = true;
+ boolean bLayersMatch = (profileLayer == layer) || profileLayer.equals(layer);
+ boolean bContextsMatch = (appContext == context) || appContext.equals(context);
+
+ if (bLayersMatch && bContextsMatch) {
+ // successful notification
+ debug("successful notification for layer=" + layer + " context=" + context);
+ } else {
+ // error - notify had problem
+ String msg = "ERROR - listener notified at wrong profileLayer: " + layer + " or context: " + context;
+ debug(msg);
+ }
+ }
+
+ private void debug(String out) {
+ System.out.println(out);
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthConfig.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthConfig.java
new file mode 100644
index 0000000..13c8da6
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthConfig.java
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.SEVERE;
+
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.config.ServerAuthContext;
+import jakarta.servlet.http.HttpServletRequest;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ *
+ * Important: It is very likely that the logged messages of this class are being searched for in the logfile by the
+ * client code. Because of this, refrain from changing log messages in this file.
+ *
+ */
+public class TSServerAuthConfig implements jakarta.security.auth.message.config.ServerAuthConfig {
+
+ protected static TSLogger logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+
+ protected static String messageLayer;
+ protected static String appContext;
+ protected static CallbackHandler handler;
+ protected static Map properties;
+ protected static Map authMandatoryMap;
+
+ protected TSServerAuthConfig(String layer, String applicationCtxt, CallbackHandler cbkHandler, Map props) {
+ messageLayer = layer;
+ appContext = applicationCtxt;
+ handler = cbkHandler;
+ properties = props;
+ }
+
+ public TSServerAuthConfig(String layer, String applicationCtxt, CallbackHandler cbkHandler, Map props, TSLogger tsLogger) {
+ this(layer, applicationCtxt, cbkHandler, props);
+
+ if (tsLogger != null) {
+ logger = tsLogger;
+ }
+
+ String str = "TSServerAuthConfig called for layer=" + layer + " : appContext=" + applicationCtxt;
+ logger.log(INFO, str);
+ }
+
+ /**
+ * Get the message layer name of this authentication context configuration object.
+ *
+ * @return the message layer name of this configuration object, or null if the configuration object pertains to an
+ * unspecified message layer.
+ */
+ @Override
+ public String getMessageLayer() {
+ logger.log(INFO, "getMessageLayer called");
+ return messageLayer;
+ }
+
+ /**
+ * Get the application context identifier of this authentication context configuration object.
+ *
+ * @return the String identifying the application context of this configuration object or null if the configuration
+ * object pertains to an unspecified application context.
+ */
+ @Override
+ public String getAppContext() {
+ logger.log(INFO, "getAppContext called");
+ return appContext;
+ }
+
+ /**
+ * Get the authentication context identifier corresponding to the request and response objects encapsulated in
+ * messageInfo.
+ *
+ * @param messageInfo a contextual Object that encapsulates the client request and server response objects.
+ *
+ * @return the auth context identifier related to the encapsulated request and response objects, or null.
+ *
+ * @throws IllegalArgumentException if the type of the message objects incorporated in messageInfo are not compatible
+ * with the message types supported by this authentication context configuration object.
+ *
+ */
+
+ @Override
+ public String getAuthContextID(MessageInfo messageInfo) {
+ logger.log(INFO, "getAuthContextID called");
+ String authContextID = null;
+
+ if (messageLayer.equals(JASPICData.LAYER_SERVLET)) {
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ authContextID = request.getServletPath() + " " + request.getMethod();
+
+ dumpServletProfileKeys(messageInfo, "getAuthContextID", JASPICData.LAYER_SERVLET);
+ } else {
+ authContextID = null;
+ }
+
+ String logMsg = "getAuthContextID() called for layer=" + messageLayer;
+ logMsg += " shows AuthContextId=" + authContextID;
+ logger.log(INFO, logMsg);
+
+ return authContextID;
+ }
+
+ /*
+ * This is a convenience method that will likely only be called once. Currently there is only one key to dump from the
+ * map, but his may change in the future.
+ */
+ private void dumpServletProfileKeys(MessageInfo msgInfo, String callerMethod, String messageLayer) {
+ Map map = msgInfo.getMap();
+
+ // for debugging only
+ // dumpAllKeyValues(map);
+
+ // lets pull out some servlet info that we can use to help uniquely
+ // identify the source of this request
+ HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage();
+ String servletName = request.getServletPath();
+
+ // see assertion JASPI:SPEC:306 (section 3.8.1.1) for details on this
+ // jsr-196 states the following key must exist for servlet profile
+ String strKey = "jakarta.security.auth.message.MessagePolicy.isMandatory";
+ if (map != null) {
+ String keyVal = (String) map.get(strKey);
+ String msg = "dumpServletProfileKeys() called with attrs: ";
+ msg += " layer=" + messageLayer;
+ msg += " servletName=" + servletName;
+ msg += " callerMethod=" + callerMethod;
+ msg += " key=" + strKey;
+
+ if (keyVal == null) {
+ msg += " value=Invalid";
+ addMandatoryStatusToMap(msgInfo, messageLayer, appContext, false);
+ } else {
+ // We dont care if Boolean.valueOf(keyVal).booleanValue() is true
+ // or false. We only care that it is a boolean value -which means
+ // this is considered a valid key-value pair.
+ msg += " value=Valid";
+ addMandatoryStatusToMap(msgInfo, messageLayer, appContext, true);
+ }
+
+ logger.log(INFO, msg);
+ }
+ }
+
+ private void addMandatoryStatusToMap(MessageInfo msgInfo, String layer, String appContext, boolean isMandatory) {
+ if (authMandatoryMap == null) {
+ authMandatoryMap = new Hashtable<>();
+ }
+
+ // see if entry already exists and if not we need to add the entry
+ Boolean booleanObj = authMandatoryMap.get(layer + appContext);
+ if (booleanObj == null) {
+ authMandatoryMap.put(layer + appContext, Boolean.valueOf(isMandatory));
+ }
+ }
+
+ private boolean getMandatoryStatusFromMap(String layer, String appContext) {
+ boolean mandatoryStatus = false;
+
+ if (layer.equals("JASPICData.LAYER_SERVLET")) {
+ if (authMandatoryMap != null) {
+ Boolean booleanObj = authMandatoryMap.get(layer + appContext);
+ mandatoryStatus = booleanObj.booleanValue();
+ } else {
+ String msg = "Could Not properly determine isMandatory status.";
+ msg += " Will return false.";
+ logger.log(INFO, msg);
+ mandatoryStatus = false;
+ }
+ }
+
+ return mandatoryStatus;
+ }
+
+ /*
+ * for debug purposes only
+ */
+ private void dumpAllKeyValues(Map map) {
+ if (map == null) {
+ logger.log(INFO, "map is null");
+ return;
+ }
+
+ Set keys = map.keySet();
+ Iterator iterator = keys.iterator();
+ while (iterator.hasNext()) {
+ String msg = "";
+ String key = (String) iterator.next();
+ if (key != null) {
+ msg = "key=" + key;
+ String val = (String) map.get(key);
+ if (val != null) {
+ msg += " value=" + val;
+ } else {
+ msg += " value=null";
+ }
+ logger.log(INFO, msg);
+ }
+ }
+ }
+
+ /**
+ * Causes a dynamic anthentication context configuration object to update the internal state that it uses to process
+ * calls to its getAuthContext method.
+ *
+ * @exception AuthException if an error occured during the update.
+ *
+ * @exception SecurityException if the caller does not have permission to refresh the configuration object.
+ */
+ @Override
+ public void refresh() {
+ logger.log(INFO, "refresh called");
+ }
+
+ /**
+ * Used to determine whether the authentication context configuration object encapsulates any protected authentication
+ * contexts.
+ *
+ * @return true if the configuration object encapsulates at least one protected authentication context. Otherwise, this
+ * method returns false.
+ */
+ @Override
+ public boolean isProtected() {
+ // To verify protected code path, always return true.
+ return true;
+ }
+
+ /**
+ * Get a ServerAuthContext instance from this ServerAuthConfig. This method should get called by the MPR.
+ *
+ *
+ * The implementation of this method returns a ServerAuthContext instance that encapsulates the ServerAuthModules used
+ * to validate requests and secure responses associated with the given operation.
+ *
+ *
+ * Specifically, this method accesses this ServerAuthConfig object with the argument operation to determine the
+ * ServerAuthModules that are to be encapsulated in the returned ServerAuthContext instance.
+ *
+ *
+ * The ServerAuthConfig object establishes the request and response MessagePolicy objects that are passed to the
+ * encapsulated modules when they are initialized by the returned ServerAuthContext instance. It is the modules'
+ * responsibility to enforce these policies when invoked.
+ *
+ * @param operation an operation identifier used to index the provided config, or null. This value must be
+ * identical to the value returned by the getOperation method for all MessageInfo objects
+ * passed to the validateRequest method of the returned ServerAuthContext.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response to be secured by the acquired
+ * authentication context. The principal and/or credentials of the Subject may be used to select or acquire the
+ * authentication context. If the Subject is not null, additional Principals or credentials (pertaining to the source of
+ * the response) may be added to the Subject. A null value may be passed to for this parameter.
+ *
+ * @param properties a Map object that may be used by the caller to augment the properties that will be passed to the
+ * encapsulated modules at module initialization. The null value may be passed for this parameter.
+ *
+ * @return a ServerAuthContext instance that encapsulates the ServerAuthModules used to secure and validate
+ * requests/responses associated with the given operation, or null (indicating that no modules are configured).
+ *
+ * @exception AuthException if this operation fails.
+ */
+ @Override
+ public ServerAuthContext getAuthContext(String operation, Subject serviceSubject, Map properties) throws AuthException {
+ String logStr = "TSServerAuthConfig.getAuthContext: layer=" + messageLayer + " : appContext=" + appContext;
+ logger.log(INFO, logStr);
+
+ logger.log(INFO,
+ "TSServerAuthConfig.getAuthContext: layer=" + messageLayer + " : appContext=" + appContext + " operationId=" + operation);
+
+ if (serviceSubject != null) {
+ properties.put(JASPICData.SVC_SUBJECT_KEY, serviceSubject);
+ logger.log(INFO, "found a non-null serviceSubject in getAuthContext()");
+ }
+
+ // Copy properties that are passed in this method to this.properties
+ //
+ // Note: this.properties is obtained from the Provider which gets those
+ // properties during provider registration time from the factory.
+ try {
+ if (TSServerAuthConfig.properties != null && properties != null) {
+ TSServerAuthConfig.properties.putAll(properties);
+ }
+ } catch (Exception ex) {
+ logger.log(INFO, "Exception : " + ex.getMessage());
+ }
+
+ checkIf115Compatible(properties);
+
+ // validate operation is correct for the message layer type
+ validateOperationId(operation, messageLayer);
+
+ try {
+ boolean bIsMand = getMandatoryStatusFromMap(messageLayer, appContext);
+ ServerAuthContext serverAuthContext =
+ new TSServerAuthContext(
+ messageLayer, appContext, handler, operation, serviceSubject, this.properties,
+ bIsMand, logger);
+
+ logStr = "TSServerAuthConfig.getAuthContext: returned non-null ServerAuthContext";
+ logger.log(INFO, logStr);
+
+ // For SOAP layer
+ logStr = "TSServerAuthConfig.getAuthContext: returned non-null" + " ServerAuthContext for operationId=" + operation;
+ logger.log(INFO, logStr);
+ return serverAuthContext;
+ } catch (Exception e) {
+ logger.log(SEVERE, "Got AuthException in TSServerAuthConfig.getAuthContext");
+ logger.log(SEVERE, e.getMessage());
+ throw new AuthException(e.getMessage());
+ }
+ }
+
+ /*
+ * this is used to help us verify JASPI:SPEC:300 This is a convenience method that will likely only be called once.
+ * Currently there is only one key to dump from the props, but this may change in the future.
+ */
+ private void checkIf115Compatible(Map properties) {
+ String msg = "layer=" + messageLayer + " appContext=" + appContext;
+
+ // Jakarta Authentication states the following key must exist if Jakarta Authorization is supported
+ // but it must NOT exist if 115 is NOT supported.
+ String strKey = "jakarta.security.jacc.PolicyContext";
+ msg += " Key=" + strKey;
+ if (properties != null) {
+ String keyVal = (String) properties.get(strKey);
+
+ if (keyVal == null) {
+ msg += " does NOT exist thus Not 115 compatible";
+ } else if (keyVal != null) {
+ msg += " does exist thus 115 compatible";
+ logger.log(INFO, "key=" + strKey + " value=" + keyVal); // XXXX -
+ // debugging
+ }
+ } else {
+ msg += " does NOT exist thus Not 115 compatible";
+ }
+
+ logger.log(INFO, msg);
+ }
+
+ /*
+ * The goal of this method is to help us verify if we have a properly constructed operationID. This method will log
+ * messages indicating if we do or do not have a valid operationID.
+ */
+ private void validateOperationId(String operation, String layer) {
+ String MNAME = "TSServerAuthConfig.validateOperationId() : ";
+ String sProfile;
+ String lstr;
+ boolean bPassed = true;
+
+ operation = operation.trim();
+ if (operation == null) {
+ logger.log(SEVERE, MNAME + " there was a null operationId and should not be!");
+ }
+
+ if (layer.equals(JASPICData.LAYER_SERVLET)) {
+ // name should consist of following format
+ //
+ // there should ONLY be one whitspace
+ sProfile = "HttpServlet profile";
+ if (operation.startsWith("http:")) {
+ // should not start with a context path
+ lstr = MNAME + sProfile + " should not start with a context path";
+ logger.log(SEVERE, lstr);
+ bPassed = false;
+ }
+
+ if ((operation.indexOf(" ") != operation.lastIndexOf(" "))) {
+ // if here then we have more than one whitespace and should not!
+ lstr = MNAME + sProfile + " found more than one whitespace.";
+ logger.log(SEVERE, lstr);
+ bPassed = false;
+ }
+
+ int ii = operation.indexOf(" ");
+ String httpMethod = operation.substring(ii);
+ httpMethod = httpMethod.trim();
+ if (!(httpMethod.equalsIgnoreCase("GET") || httpMethod.equalsIgnoreCase("POST") || httpMethod.equalsIgnoreCase("PUT"))) {
+ // it should be one of these three supported http methods
+ lstr = MNAME + sProfile + " invalid http method type :" + httpMethod + ". Must be POST|GET|PUT";
+ logger.log(SEVERE, lstr);
+ bPassed = false;
+ }
+
+ if (bPassed) {
+ logger.log(INFO, MNAME + sProfile + " : PASSED");
+ } else {
+ logger.log(SEVERE, MNAME + sProfile + " : FAILED");
+ }
+
+ } else if (layer.equals(JASPICData.LAYER_SOAP)) {
+ // Nothing to verify here for SOAP profile
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthContext.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthContext.java
new file mode 100644
index 0000000..6f4902e
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/config/TSServerAuthContext.java
@@ -0,0 +1,586 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.config;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SERVLET;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SOAP;
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.SVC_SUBJECT_KEY;
+import static java.util.logging.Level.INFO;
+
+import ee.jakarta.tck.authentication.test.basic.sam.module.servlet.TSServerAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.servlet.TSServletWrapperSAM;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSAuthExceptionServerAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSFailureServerAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSSendFailureServerAuthModule;
+import ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSSendSuccessServerAuthModule;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import jakarta.security.auth.message.module.ServerAuthModule;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponseWrapper;
+import java.util.Map;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ *
+ * Important: It is very likely that the logged messages of this class are being searched for in the logfile by the
+ * client code. Because of this, refrain from changing log messages in this file.
+ *
+ */
+public class TSServerAuthContext implements jakarta.security.auth.message.config.ServerAuthContext {
+
+ private static ServerAuthModule serverAuthModule;
+ private static String messageLayer;
+ private static Map properties;
+ private static TSLogger logger;
+
+ private static String soapUPTokenAppContext = "HelloService HelloPort";
+ private static String servletUPTokenAppContext = "spitests_servlet_web";
+
+ private static MessageInfo messageInfoFromVerifyReq;
+
+ private static boolean isMandatory = false;
+
+ /** Creates a new instance of ServerAuthContext */
+ public TSServerAuthContext() {
+ }
+
+ public TSServerAuthContext(String messageLayer, String appContext, CallbackHandler handler, String operation, Subject clientSubject,
+ Map properties, boolean isAuthMandatory, TSLogger tsLogger) throws AuthException {
+ this(messageLayer, appContext, handler, operation, clientSubject, properties);
+
+ logger = tsLogger;
+ logger.log(INFO, "TSServerAuthContext called");
+ String logStr = "TSServerAuthContext called for messageLayer=" + messageLayer + " : appContext=" + appContext;
+ logger.log(INFO, logStr);
+ logStr += " : operation=" + operation;
+ logger.log(INFO, logStr);
+
+ ServerAuthModule sam = null;
+ properties.put("TSLogger", logger);
+
+ isMandatory = isAuthMandatory;
+
+ // Create a TargetPolicy for AUTHENTICATE_SENDER
+ MessagePolicy.TargetPolicy msgTargetPolicy =
+
+ new MessagePolicy.TargetPolicy(null, new MessagePolicy.ProtectionPolicy() {
+ @Override
+ public String getID() {
+ return AUTHENTICATE_SENDER;
+ }
+ });
+ MessagePolicy.TargetPolicy[] msgTargetPolicies = { msgTargetPolicy };
+ MessagePolicy requestMessagePolicy = new MessagePolicy(msgTargetPolicies, isMandatory);
+
+ // Create a TargetPolicy for AUTHENTICATE_CONTENT
+ MessagePolicy.TargetPolicy msgTargetPolicyContent =
+
+ new MessagePolicy.TargetPolicy(null, new MessagePolicy.ProtectionPolicy() {
+ @Override
+ public String getID() {
+ return AUTHENTICATE_CONTENT;
+ }
+ });
+ MessagePolicy.TargetPolicy[] msgTargetPoliciesContent = { msgTargetPolicyContent };
+ MessagePolicy responseMessagePolicy = new MessagePolicy(msgTargetPoliciesContent, isMandatory);
+
+ // Note: We could also choose auth modules based on appContext but
+ // MessageLayer seems to be the ideal candidate for choosing
+ // auth modules.
+ if (messageLayer.equals(LAYER_SOAP)) {
+
+ if (appContext.equals(soapUPTokenAppContext)) {
+ sam = new ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSServerAuthModule();
+ sam.initialize(requestMessagePolicy, responseMessagePolicy, handler, properties);
+ } else if (appContext.indexOf("SendSuccessHello") > -1) {
+ sam = new TSSendSuccessServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("SendFailureHello") > -1) {
+ sam = new TSSendFailureServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("FailureHello") > -1) {
+ sam = new TSFailureServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+
+ } else if (appContext.indexOf("AuthExceptionHello") > -1) {
+ sam = new TSAuthExceptionServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+
+ } else {
+ sam = new ee.jakarta.tck.authentication.test.basic.sam.module.soap.TSServerAuthModule();
+ sam.initialize(null, null, handler, properties);
+ }
+
+ } else if (messageLayer.equals(LAYER_SERVLET)) {
+ System.out.println("AppContext =" + appContext);
+
+ if (appContext.contains(servletUPTokenAppContext) && operation.contains("WrapperServlet")) {
+ sam = new TSServletWrapperSAM();
+ sam.initialize(requestMessagePolicy, responseMessagePolicy, handler, properties);
+ } else if (appContext.contains(servletUPTokenAppContext)) {
+ sam = new TSServerAuthModule();
+ sam.initialize(requestMessagePolicy, responseMessagePolicy, handler, properties);
+ } else {
+ sam = new TSServerAuthModule();
+ sam.initialize(requestMessagePolicy, null, handler, properties);
+ }
+ }
+
+ serverAuthModule = sam;
+ }
+
+ /*
+ * This should be private so that we can be sure people pass a valid TSLogger into the public constructor.
+ */
+ private TSServerAuthContext(String layer, String appCtxt, CallbackHandler callbackHandler, String optn, Subject clientSubject, Map props) throws AuthException {
+ messageLayer = layer;
+ properties = props;
+ }
+
+ /**
+ * Authenticate a received service request.
+ *
+ * This method is called to transform the mechanism specific request message acquired by calling getRequestMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the received
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into a corresponding mechanism specific response message, or to the validated application request message. The
+ * runtime will bind a validated application message into the the corresponding service invocation.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request. It is used by the method
+ * implementation to store Principals and credentials validated in the request.
+ *
+ * @param serviceSubject a Subject that represents the recipient of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the request. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully validated. The validated request message
+ * is available by calling getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_SUCCESS to indicate that validation/processing of the request message successfully produced the
+ * secured application response message (in messageInfo). The secured response message is available by calling
+ * getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that message validation is incomplete, and that a preliminary response was
+ * returned as the response message in messageInfo.
+ *
+ * When paththis status value is returned to challenge an application request message, the challenged request must be
+ * saved by the authentication module such that it can be recovered when the module's validateRequest message is called
+ * to process the request returned for the challenge.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that message validation failed and that an appropriate failure response
+ * message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ Object reqObj = null;
+
+ String msg = "TSServerAuthContext.validateRequest called";
+
+ // This msg used to verify assertion: JASPI:SPEC:50
+ logger.log(INFO, msg);
+
+ // This msg used to verify assertion: JASPI:SPEC:88
+ msg += " for layer=" + messageLayer;
+ logger.log(INFO, msg);
+
+ // The following msg used to verify assertion: JASPI:SPEC:89
+ if (messageInfo != null) {
+ reqObj = messageInfo.getRequestMessage();
+ if (reqObj != null) {
+ // if here, we want to see if our reqObj is type HttpServletRequest
+ if (reqObj instanceof HttpServletRequest) {
+ String contextPath = ((HttpServletRequest) reqObj).getContextPath();
+ String servletPath = ((HttpServletRequest) reqObj).getServletPath();
+
+ // note: we are leaving off the pathInfo since we only want
+ // to log contextPath and servletPath info so it's
+ // more of a pseudo requestURI we are validating but
+ // note that this will match our client so should be fine.
+ String requestURI = contextPath + servletPath;
+ msg += " for requestURI=" + requestURI;
+ } else {
+ msg += " reqObj instanceof=" + reqObj.getClass().getName();
+ }
+ } else {
+ msg += " reqObj=NULL";
+ }
+ }
+
+ // Used to assist with the verification of assertion JASPI:SPEC:52
+ String subjStr = messageLayer + " profile: ";
+ if (clientSubject != null) {
+ subjStr += "TSServerAuthContext.validateRequest called with non-null client Subject";
+ } else {
+ subjStr += "TSServerAuthContext.validateRequest called with null client Subject";
+ }
+ logger.log(INFO, subjStr);
+
+ // used to assist with the verification of assertion JASPI:SPEC:52
+ verifyClientSubject(clientSubject);
+
+ // used to assist with the verification of assertion JASPI:SPEC:53 and
+ // JASPI:SPEC:313
+ verifyServiceSubject(serviceSubject);
+
+ AuthStatus authStatus = serverAuthModule.validateRequest(messageInfo, clientSubject, serviceSubject);
+
+ logger.log(INFO, msg);
+
+ dumpAuthStatusString(authStatus, msg);
+
+ // save off the MessageInfo object instance so that we can verify the
+ // same one is used in the call to SecureRequest (JASPI:SPEC:60)
+ messageInfoFromVerifyReq = messageInfo;
+
+ return authStatus;
+ }
+
+ public void dumpAuthStatusString(AuthStatus rval, String msg) {
+ if (msg == null) {
+ msg = "";
+ }
+
+ if (rval == AuthStatus.SUCCESS) {
+ msg += " AuthStatus=AuthStatus.SUCCESS";
+ } else if (rval == AuthStatus.FAILURE) {
+ msg += " AuthStatus=AuthStatus.FAILURE";
+ } else if (rval == AuthStatus.SEND_SUCCESS) {
+ msg += " AuthStatus=AuthStatus.SEND_SUCCESS";
+ } else if (rval == AuthStatus.SEND_FAILURE) {
+ msg += " AuthStatus=AuthStatus.SEND_FAILURE";
+ } else if (rval == AuthStatus.SEND_CONTINUE) {
+ msg += " AuthStatus=AuthStatus.SEND_CONTINUE";
+ } else {
+ msg += " AuthStatus=" + rval;
+ }
+
+ logger.log(INFO, msg);
+ }
+
+ /*
+ * This verifies the client subject object for validateRequest() calls. This is used to assist with the verification of
+ * assertion JASPI:SPEC:52 by logging information about the state of the clientSubject The spec (section 2.1.5) states
+ * that clientSubject can not be null and that it can not be read-only.
+ *
+ */
+ public void verifyClientSubject(Subject clientSubject) {
+ String msg = "";
+
+ if (clientSubject == null) {
+ // this is failure against the spec
+ msg = "FAILURE detected - ClientSubjects should not be null.";
+ } else {
+ msg = "Valid ClientSubjects - it was not null.";
+ }
+ logger.log(INFO, msg);
+
+ if (clientSubject != null) {
+ if (clientSubject.isReadOnly()) {
+ // this is failure against the spec
+ msg = "FAILURE detected - ClientSubjects should not be read-only.";
+ } else {
+ msg = "Valid ClientSubjects - it was not read-only.";
+ }
+ logger.log(INFO, msg);
+ }
+
+ }
+
+ /*
+ * This verifies the service subject object for validateRequest() calls. This is used to assist with the verification of
+ * assertion JASPI:SPEC:53 by logging information regarding wether or not the serviceSubject passed into validateRequest
+ * was the same as what was used to acquire the ServerAuthContext.
+ */
+ public void verifyServiceSubject(Subject serviceSubject) {
+ String msg = "";
+ String key = JASPICData.SVC_SUBJECT_KEY;
+ Subject value = (Subject) properties.get(key);
+
+ if (value != null) {
+ msg = "got a non-null subject out of the map";
+ logger.log(INFO, msg);
+
+ if (serviceSubject == null) {
+ msg = "FAILURE detected - ServiceSubjects should be the same and are not.";
+ } else if (value.equals(serviceSubject)) {
+ msg = "ServiceSubjects correctly matched.";
+ } else {
+ // if here, serviceSubjects dont match but should
+ msg = "FAILURE detected - ServiceSubjects should be the same and are not.";
+ }
+ logger.log(INFO, msg);
+
+ if ((serviceSubject != null) && (value.equals(serviceSubject))) {
+ // to help verify assertion JASPI:SPEC:313 (per spec section 2.1.5.2):
+ // If a non-null Subject was used to call the ServerAuthContext
+ // the same Subject must be passed as the serviceSubject in this
+ // call. If a non-null serviceSubject is used in this call, it
+ // must not be read-only
+ if (serviceSubject.isReadOnly()) {
+ // should not get here.
+ msg = "FAILURE detected - ServiceSubjects should not be read-only.";
+ logger.log(INFO, msg);
+ } else {
+ msg = "Valid ServiceSubjects - it was not read-only.";
+ logger.log(INFO, msg);
+ }
+ }
+ }
+ }
+
+ /**
+ * Secure a service response before sending it to the client.
+ *
+ * This method is called to transform the response message acquired by calling getResponseMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. It may be used by the
+ * method implementation to retrieve Principals and credentials necessary to secure the response. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SEND_SUCCESS when the application response message was successfully secured. The secured response
+ * message may be obtained by calling by getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application response message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response (in the form of a request) from the peer.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by processing at least one additional request/response
+ * exchange (after having sent the response message returned in messageInfo).
+ *
+ * When this status value is returned, the application response must be saved by the authentication module such that it
+ * can be recovered when the module's validateRequest message is called to process the elicited response.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that a failure occured while securing the response message and that an
+ * appropriate failure response message is available by calling getResponseMeessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ AuthStatus rval = AuthStatus.SUCCESS;
+ Object reqObj = null;
+ Object respObj = null;
+ String msg = "TSServerAuthContext.secureResponse called";
+
+ // This msg used to verify assertion: JASPI:SPEC:130
+ logger.log(INFO, msg);
+
+ msg = "secureResponse called for layer=" + messageLayer;
+
+ try {
+ if (messageInfo != null) {
+
+ verifyMessageInfoObjsMatch(messageInfo); // JASPI:SPEC:60
+
+ reqObj = messageInfo.getRequestMessage();
+ respObj = messageInfo.getResponseMessage();
+ if (reqObj != null) {
+ // if here, we want to see if our reqObj is type HttpServletRequest
+ if (reqObj instanceof HttpServletRequest) {
+ String contextPath = ((HttpServletRequest) reqObj).getContextPath();
+ String servletPath = ((HttpServletRequest) reqObj).getServletPath();
+
+ // note: we are leaving off the pathInfo since we only want
+ // to log contextPath and servletPath info so it's
+ // more of a pseudo requestURI we are validating but
+ // note that this will match our client so should be fine.
+ String requestURI = contextPath + servletPath;
+ msg += " for requestURI=" + requestURI;
+ } else {
+ msg += " reqObj instanceof=" + reqObj.getClass().getName();
+ }
+ } else {
+ msg += " reqObj=NULL";
+ }
+ }
+ logger.log(INFO, msg);
+
+ // used to assist with the verification of assertion JASPI:SPEC:61
+ verifySecureRespServiceSubject(serviceSubject);
+
+ rval = serverAuthModule.secureResponse(messageInfo, serviceSubject);
+ msg = "";
+ dumpAuthStatusString(rval, msg);
+
+ if (rval.equals(AuthStatus.SUCCESS)) {
+ // explicitly set return code but remember that we must be sure the
+ // response we stuff into the MessageInfo is wrapped in a
+ // HttpServletResponseWrapper object (jsr-196 spec section 3.8.3.4)
+ if (respObj != null) {
+ ((HttpServletResponse) respObj).setStatus(HttpServletResponse.SC_OK);
+ HttpServletResponseWrapper respWrapper = null;
+ if (!(reqObj instanceof jakarta.servlet.http.HttpServletResponseWrapper)) {
+ respWrapper = new HttpServletResponseWrapper((HttpServletResponse) respObj);
+ respWrapper.setStatus(HttpServletResponse.SC_OK);
+ messageInfo.setResponseMessage(respWrapper);
+ } else {
+ messageInfo.setResponseMessage(respObj);
+ }
+
+ logger.log(INFO, "Set the responseObjects return status to OK==200");
+ } else {
+ logger.log(INFO, "ResponseObject == null so we could NOT set response status");
+ }
+ } else {
+ logger.log(INFO, "authStatus != SUCCESS so not setting response object status == 200");
+ }
+ } catch (AuthException ex) {
+ logger.log(INFO, "Got AuthException");
+ ex.printStackTrace();
+ throw ex;
+ } catch (Exception ex) {
+ logger.log(INFO, "Got generic Exception");
+ ex.printStackTrace();
+ }
+
+ return rval;
+ }
+
+ /*
+ * This is used to assist with verifying assertion: JASPI:SPEC:60 This is a convenience method that is used to verify if
+ * the passed in messageInfo object (which should be from secureRequest()) matches our previously saved off messageInfo
+ * object (which should be from our last call to validateRequest() - which we saved off in a static var.
+ */
+ public void verifyMessageInfoObjsMatch(MessageInfo messageInfo) {
+ String err = "FAILURE: MessageInfo object in secureRequest does not";
+ err += " match the messageInfo object from validateRequest";
+
+ String msg = "MessageInfo object from secureRequest matches the ";
+ msg += " messageInfo object from validateRequest";
+
+ // verify the passed in messageInfo
+ if ((messageInfo == null) && (messageInfoFromVerifyReq == null)) {
+ logger.log(INFO, msg);
+ } else if ((messageInfo == null) || (messageInfoFromVerifyReq == null)) {
+ logger.log(INFO, err);
+ if (messageInfo == null) {
+ msg = "Failure: secureRequest had null obj but validateRequest did not";
+ logger.log(INFO, msg);
+ } else {
+ msg = "Failure: validateRequest had null obj but secureResponse did not";
+ logger.log(INFO, msg);
+ }
+ } else if (!messageInfoFromVerifyReq.equals(messageInfo)) {
+ logger.log(INFO, err);
+ logger.log(INFO, "FAILURE: messageInfo objects non-null but don't match");
+ } else {
+ logger.log(INFO, msg);
+ }
+
+ return;
+ }
+
+ /*
+ * This verifies the service subject object for secureResponse() calls. Spec says: (re: Pt 2 in MPR) "If a non-null
+ * serviceSubject is used in this call, it must not be read-only and the same serviceSubject must be passed in the call
+ * to secureResponse for the corresponding response (if there is one)."
+ *
+ */
+ public void verifySecureRespServiceSubject(Subject serviceSubject) {
+ Subject subjectFromProperties = (Subject) properties.get(SVC_SUBJECT_KEY);
+
+ if (subjectFromProperties != null) {
+ logger.log(INFO, "Got a non-null subject out of the map");
+
+ if (serviceSubject == null) {
+ logger.log(INFO, "FAILURE detected - SecureResponse ServiceSubjects should be the same and are not.");
+ } else if (subjectFromProperties.equals(serviceSubject)) {
+ logger.log(INFO, "SecureResponse ServiceSubjects correctly matched.");
+ } else {
+ // If here, service subjects don't match but should
+ logger.log(INFO, "FAILURE detected - SecureResponse ServiceSubjects should be the same and are not.");
+ }
+
+ if ((serviceSubject != null) && (subjectFromProperties.equals(serviceSubject))) {
+ // To help verify assertion JASPI:SPEC:313 (per spec section 2.1.5.2):
+ // If a non-null Subject was used to call the ServerAuthContext
+ // the same Subject must be passed as the serviceSubject in this
+ // call. If a non-null serviceSubject is used in this call, it
+ // must not be read-only
+ if (serviceSubject.isReadOnly()) {
+ // Should not get here.
+ logger.log(INFO, "FAILURE detected - SecureResponse ServiceSubjects should not be read-only.");
+ } else {
+ logger.log(INFO, "Valid SecureResponse ServiceSubjects - it was not read-only.");
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Remove method specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logger.log(INFO, "TSServerAuthContext.cleanSubject called");
+
+ serverAuthModule.cleanSubject(messageInfo, subject);
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSClientAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSClientAuthModule.java
new file mode 100644
index 0000000..b1704ef
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSClientAuthModule.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.servlet;
+
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * This is a placeholder file that should not end up getting used by the servlet profile. Ideally we should be able to
+ * search the log file for strings from this class and we should not see any of those entries getting logged.
+ *
+ * @author Sun Microsystems
+ */
+public class TSClientAuthModule implements jakarta.security.auth.message.module.ClientAuthModule {
+ private TSLogger logger = null;
+
+ /**
+ * Creates a new instance of ClientAuthModuleImpl
+ */
+ public TSClientAuthModule() {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ logMsg("TSClientAuthModule() constructor called.");
+ }
+
+ public TSClientAuthModule(TSLogger log) {
+ if (log != null) {
+ logger = log;
+ } else {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ }
+ logMsg("TSClientAuthModule(TSLogger) constructor called.");
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options)
+ throws AuthException {
+
+ if ((options != null) && (options.get("TSLogger") != null)) {
+ logger = (TSLogger) options.get("TSLogger");
+ }
+
+ logMsg("TSClientAuthModule.initialize() called.");
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects where each element defines a message type supported by the module. A module should
+ * return an array containing at least one element. An empty array indicates that the module will attempt to support any
+ * message type. This method never returns null.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ logMsg("TSClientAuthModule.getSupportedMessageTypes() called.");
+ Class[] classarray = { jakarta.servlet.http.HttpServletRequest.class, jakarta.servlet.http.HttpServletResponse.class };
+ return classarray;
+ }
+
+ /**
+ * Secure a service request message before sending it to the service.
+ *
+ * This method is called to transform the request message acquired by calling getRequestMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to secure the request. If the Subject is
+ * not null, the method implementation may add additional Principals or credentials (pertaining to the source of the
+ * service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully secured. The secured request message may
+ * be obtained by calling by getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application request message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response from the peer security system. This status value
+ * also indicates that the application message has not yet been secured.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange after having received the security-specific response elicited by sending the security message.
+ *
+ * When this status value is returned, the corresponding invocation of validateResponse must be able to
+ * obtain the original application request message.
+ *
+ *
AuthStatus.FAILURE to indicate that a failure occured while securing the request message, and that an appropriate
+ * failure response message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
+
+ logMsg("TSClientAuthModule.secureRequest() called.");
+ return AuthStatus.SUCCESS;
+ }
+
+ /**
+ * Validate a received service response.
+ *
+ * This method is called to transform the mechanism specific response message acquired by calling getResponseMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the response
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into the next mechanism specific request message to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the recipient of the service response, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the response. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application response message was successfully validated. The validated message is
+ * available by calling getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that response validation is incomplete, and that a continuation request was
+ * returned as the request message within messageInfo.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange.
+ *
+ *
AuthStatus.FAILURE to indicate that validation of the response failed, and that a failure response message has
+ * been established in messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ logMsg("TSClientAuthModule.validateResponse() called.");
+ return AuthStatus.SUCCESS;
+ }
+
+ /**
+ * Remove implementation specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSClientAuthModule.cleanSubject() called.");
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSRequestWrapper.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSRequestWrapper.java
new file mode 100644
index 0000000..4c90978
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSRequestWrapper.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.servlet;
+
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Map;
+import java.util.logging.Level;
+
+public class TSRequestWrapper extends HttpServletRequestWrapper {
+ private TSLogger logger = null;
+
+ Map optionsMap = null;
+
+ public TSRequestWrapper(HttpServletRequest request) {
+ super(request);
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ logMsg("TSRequestWrapper constructor called");
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+
+ if ("isRequestWrapped".equals(name)) {
+ return Boolean.TRUE;
+ }
+
+ return super.getAttribute(name);
+ }
+
+ @Override
+ public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
+
+ boolean bval = super.authenticate(response);
+
+ debug("made it into TSRequestWrapper.authenticate()");
+
+ //
+ // NOTE:
+ // It is not clear that flow will make it into this method. So we will
+ // write out possible errors messages below and then check for occurances
+ // of those error messages from within the tests in spi/servlet.
+ //
+
+ // do some checks and validation relates to JASPIC 1.1 spec
+ // section 3.8.4 (para 1) per assertion JASPIC:SPEC:322
+ if (bval) {
+ String msg = "";
+ // "Both cases, must also ensure that the value returned by calling
+ // getAuthType on the HttpServletRequest is consistent in terms of
+ // being null or non-null with the value returned by getUserPrincipal."
+ if ((super.getAuthType() != null) && super.getRemoteUser() != null) {
+ // This is good - both non-null so this is okay
+ msg = "HttpServletRequest authentication results match with getAuthType() and getRemoteUser()";
+ } else if ((super.getAuthType() == null) && super.getRemoteUser() == null) {
+ // This is good - both null, so this is okay too
+ msg = "HttpServletRequest authentication results match with getAuthType() and getRemoteUser()";
+ } else {
+ // This is bad - must be mismatch between getAuthType() and
+ // getRemoteUser()
+ msg = "ERROR - HttpServletRequest authentication result mis-match with getAuthType() and getRemoteUser()";
+ }
+ logger.log(Level.INFO, msg);
+ }
+
+ // test for assertion: JASPIC:SPEC:323 from spec section 3.8.4, para 2:
+ // check if getAuthType() != null, and if not null, then check if
+ // MessageInfo Map
+ // sets/users key=jakarta.servlet.http.authType. If so, getAuthType should be
+ // set
+ // set to value of key. getAuthType should not be null on successful authN.
+ if (bval) {
+ String msg = "";
+
+ if ((super.getAuthType() != null) && (optionsMap != null)) {
+ // see if key=jakarta.servlet.http.authType exists and if so, make
+ // sure it matches the getAuthType() value
+ if (optionsMap.get("jakarta.servlet.http.authType") != null) {
+ // if here, then we need to make sure the value specified for
+ // getAuthType matches this value.
+ String val = (String) optionsMap.get("jakarta.servlet.http.authType");
+ if (val == null) {
+ // spec violation - cant be null if key exists!!!
+ msg = "ERROR - invalid setting for jakarta.servlet.http.authType = null";
+ } else if (!val.equalsIgnoreCase(super.getAuthType())) {
+ // spec violation - these have to match!!
+ msg = "ERROR - mismatch value set for jakarta.servlet.http.authType and getAuthType()";
+ } else {
+ // we are good if here.
+ msg = "getAuthType() matches value for jakarta.servlet.http.authType";
+ }
+ logger.log(Level.INFO, msg);
+ debug(msg);
+ debug("authenticate(): getAuthType() = " + super.getAuthType());
+ debug("authenticate(): jakarta.servlet.http.authType = " + val);
+ }
+ }
+
+ }
+
+ return bval;
+ }
+
+ public void setOptionsMap(Map options) {
+ optionsMap = options;
+ }
+
+ public Map getOptionsMap() {
+ return optionsMap;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+ public void debug(String str) {
+ System.out.println("TSRequestWrapper: " + str);
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSResponseWrapper.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSResponseWrapper.java
new file mode 100644
index 0000000..d5a1683
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSResponseWrapper.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.servlet;
+
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponseWrapper;
+import java.util.logging.Level;
+
+public class TSResponseWrapper extends HttpServletResponseWrapper {
+ private TSLogger logger = null;
+
+ public TSResponseWrapper(HttpServletResponse response) {
+ super(response);
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ logMsg("TSResponseWrapper constructor called");
+ }
+
+ @Override
+ public String getHeader(String name) {
+
+ if ("isResponseWrapped".equals(name)) {
+ return "true";
+ }
+
+ return super.getHeader(name);
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSServerAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSServerAuthModule.java
new file mode 100644
index 0000000..760f2c5
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSServerAuthModule.java
@@ -0,0 +1,730 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.servlet;
+
+import static java.util.logging.Level.INFO;
+
+import ee.jakarta.tck.authentication.test.basic.sam.CommonCallbackSupport;
+import ee.jakarta.tck.authentication.test.basic.sam.ServerCallbackSupport;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponseWrapper;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Sun Microsystems
+ */
+public class TSServerAuthModule implements jakarta.security.auth.message.module.ServerAuthModule {
+ private TSLogger logger;
+
+ private static CallbackHandler callbackHandler;
+
+ /**
+ * Creates a new instance of TSServerAuthModule
+ */
+ public TSServerAuthModule() {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ logMsg("TSServerAuthModule() constructor called");
+ }
+
+ public TSServerAuthModule(TSLogger log) {
+ if (log != null) {
+ logger = log;
+ } else {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ }
+ logMsg("TSServerAuthModule(TSLogger) constructor called");
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options)
+ throws AuthException {
+
+ if ((options != null) && options.get("TSLogger") != null) {
+ logger = (TSLogger) options.get("TSLogger");
+ }
+
+ callbackHandler = handler;
+
+ // perform some checking to support assertion JASPI:SPEC:87
+ verifyRequestPolicy(requestPolicy);
+
+ logger.log(INFO, "CBH for HttpServlet supports type: " + handler.getClass().getName());
+ }
+
+ /*
+ * This is a convenience method that will do some verification on the request policy to see if it complies with
+ * assertion JASPI:SPEC:87. If there are any problems found, appropriate log statements will be made and searched for
+ * later on in the Client code.
+ */
+ private void verifyRequestPolicy(MessagePolicy requestPolicy) {
+
+ String errStr = "Layer=" + JASPICData.LAYER_SERVLET;
+ errStr += " requestPolicy=invalid in TSServerAuthModule.initialize()";
+
+ if (requestPolicy == null) {
+ // we should never have a null requestpolicy here
+ logger.log(Level.SEVERE, errStr);
+ } else {
+ MessagePolicy.TargetPolicy[] tp = requestPolicy.getTargetPolicies();
+ if (tp.length < 1) {
+ // must return an array containing at least one TargetPolicy
+ logger.log(INFO, errStr);
+ } else {
+ for (int ii = 0; ii < tp.length; ii++) {
+ MessagePolicy.ProtectionPolicy pp = tp[ii].getProtectionPolicy();
+ if ((pp != null) && (!isProtectionPolicyIDValid(pp.getID()))) {
+ String str = "Layer=" + JASPICData.LAYER_SERVLET;
+ str += " Invalid ProtectionPolicy.getID()";
+ logger.log(INFO, str);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * (spec section 3.7.4) For servlet profile, calling the getID() method on the ProtectionPolicy must return one of the
+ * following values: ProtectionPolicy.AUTHENTICATE_SENDER ProtectionPolicy.AUTHENTICATE_CONTENT
+ */
+ public boolean isProtectionPolicyIDValid(String strId) {
+ boolean bval = false;
+
+ if ((strId.equals(MessagePolicy.ProtectionPolicy.AUTHENTICATE_CONTENT))
+ || (strId.equals(MessagePolicy.ProtectionPolicy.AUTHENTICATE_SENDER))) {
+ bval = true;
+ }
+ return bval;
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects, with at least one element defining a message type supported by the module.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ logMsg("TSServerAuthModule.getSupportedMessageTypes called");
+ Class[] classarray = { jakarta.servlet.http.HttpServletRequest.class, jakarta.servlet.http.HttpServletResponse.class };
+ return classarray;
+ }
+
+ /**
+ * Authenticate a received service request.
+ *
+ * This method is called to transform the mechanism specific request message acquired by calling getRequestMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the received
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into a corresponding mechanism specific response message, or to the validated application request message. The
+ * runtime will bind a validated application message into the the corresponding service invocation.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request. It is used by the method
+ * implementation to store Principals and credentials validated in the request.
+ *
+ * @param serviceSubject a Subject that represents the recipient of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the request. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully validated. The validated request message
+ * is available by calling getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_SUCCESS to indicate that validation/processing of the request message successfully produced the
+ * secured application response message (in messageInfo). The secured response message is available by calling
+ * getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that message validation is incomplete, and that a preliminary response was
+ * returned as the response message in messageInfo.
+ *
+ * When this status value is returned to challenge an application request message, the challenged request must be saved
+ * by the authentication module such that it can be recovered when the module's validateRequest message is called to
+ * process the request returned for the challenge.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that message validation failed and that an appropriate failure response
+ * message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ String servletPath = request.getContextPath() + request.getServletPath();
+
+ String msg = "HttpServlet profile: ";
+
+ if (clientSubject != null) {
+ msg += "TSServerAuthModule.validateRequest called with non-null client Subject";
+ // msg += " principal=" + getPrincipalNameFromSubject(clientSubject);
+ } else {
+ msg += "TSServerAuthModule.validateRequest called with null client Subject";
+ }
+ logMsg(msg);
+
+ // lets ensure we are not pre-logged in
+ doCheckForPreLogin(messageInfo, clientSubject, serviceSubject);
+
+ if (serviceSubject != null) {
+ msg = msg + " with serviceSubject :" + getPrincipalNameFromSubject(serviceSubject);
+ } else {
+ msg = msg + " with null serviceSubject";
+ }
+ logMsg(msg);
+
+ // verify any profile keys
+ logMessageTypes(messageInfo, "validateRequest");
+ dumpServletProfileKeys(messageInfo, "validateRequest");
+
+ // this is used to help us verify part of JASPI:SPEC:98
+ // if auth is optional then we should be able to have a null
+ // principal. If auth is mandatory, then we need to set a
+ // principal object with some valid creds.
+ boolean bIsMandatory = isAuthMandatory(messageInfo);
+
+ // support to test validateRequest is called regardless of whether authN
+ // is required (including when isMandatory is false)
+ logMsg("validateRequest() called for " + servletPath + ", isMandatory() = " + bIsMandatory);
+
+ // Check Callback Handler support for server runtime
+ logMsg("Dispatching to request for servletPath: " + servletPath);
+ CommonCallbackSupport commonCallbacks = new CommonCallbackSupport(logger, callbackHandler, JASPICData.LAYER_SERVLET,
+ "ServerRuntime");
+ commonCallbacks.verify();
+
+ doServerCallbackChecks(messageInfo, clientSubject, serviceSubject);
+
+ // Determine return status based on pre-canned context ids
+ AuthStatus returnStatus = getReturnStatus(messageInfo, clientSubject);
+
+ setSpecialRequestAttribute(messageInfo, "validateReqCalled", "true");
+
+ return returnStatus;
+ }
+
+ /*
+ * This method checks if a user is pre-logged in for a servlet that required no authen. In such a case, we should NOT
+ * see any pre-authenticated status. This method should be called before any callback handler invocations occur.
+ */
+ private boolean doCheckForPreLogin(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) {
+
+ boolean rval = true;
+ String theServlet = "OpenToAllServlet";
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ String servletPath = request.getContextPath() + request.getServletPath();
+
+ if (servletPath.contains(theServlet)) {
+ // we found our request for the servlet that should have
+ // open perms and thus NOT require any authentication.
+ Principal callerPrincipal = request.getUserPrincipal();
+
+ if (callerPrincipal == null) {
+ // if here, we are good since we are not logged in (based on the
+ // premise that if logged in, calling getUserPrincipal() would
+ // have returned a non-null value.)
+ logMsg("Validated we are not prelogged in for " + theServlet);
+ } else {
+ // ERROR - something was non-null which indicates that we are
+ // pre-logged in (e.g. pre-authenticated) for a scenario that does
+ // not require authentication. Either that or we are (correctly)
+ // not logged in *but* are incorrectly getting back non-null values
+ // when not logged in nor authenticated.
+ logMsg("Failed validation check for being pre-logged in.");
+ logMsg("doCheckForPreLogin(): request.getUserPrincipal() = null");
+ rval = false;
+ }
+ }
+
+ return rval;
+ }
+
+ private void doServerCallbackChecks(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ String servletPath = request.getContextPath() + request.getServletPath();
+ String msg = "";
+
+ ServerCallbackSupport serverCallbacks =
+ new ServerCallbackSupport(
+ logger, callbackHandler, JASPICData.LAYER_SERVLET, messageInfo,
+ clientSubject, serviceSubject);
+
+ // instead of calling all callbacks in one method, lets call them
+ // all individually so ithat we can check return values of each.
+ // serverCallbacks.verify();
+
+ if (serverCallbacks.verifyCPCCallback()) {
+ msg = "TSServerAuthModule.validateRequest(): verifyCPCCallback returned true";
+ } else {
+ msg = "TSServerAuthModule.validateRequest(): verifyCPCCallback returned false";
+ }
+ msg += " for servletPath = " + servletPath;
+ logMsg(msg);
+
+ if (serverCallbacks.verifyGPCCallback()) {
+ msg = "TSServerAuthModule.validateRequest(): verifyGPCCallback returned true";
+ } else {
+ msg = "TSServerAuthModule.validateRequest(): verifyGPCCallback returned false";
+ }
+ msg += " for servletPath = " + servletPath;
+ logMsg(msg);
+
+ if (serverCallbacks.verifyPVCCallback()) {
+ msg = "TSServerAuthModule.validateRequest(): verifyPVCCallback returned true";
+ } else {
+ msg = "TSServerAuthModule.validateRequest(): verifyPVCCallback returned false";
+ }
+ msg += " for servletPath = " + servletPath;
+ logMsg(msg);
+
+ return;
+ }
+
+ /*
+ * This method will have some pre-canned status responses built into based on what the user name is. We will return
+ * status codes based on the passed in context info.
+ *
+ * One goal of this method is to cause a Callbackhandler to be invoked such that the Callbackhandler will return an
+ * AuthStatus code that matches our pre-canned (returned) AuthStatus.
+ */
+ private AuthStatus getReturnStatus(MessageInfo msgInfo, Subject subject) throws AuthException {
+ AuthStatus rval = AuthStatus.SUCCESS;
+ String strStatus = "AuthStatus.SUCCESS";
+ String msg;
+ int statusCode = 200;
+
+ // get request object
+ HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage();
+
+ // get name of servlet(servletPath) and not the app (eg context path)
+ String servletName = request.getServletPath();
+
+ msg = "HttpServlet profile with servletName=" + servletName;
+ if (servletName.contains(JASPICData.AUTHSTAT_SENDFAILURE_ND)) {
+ rval = AuthStatus.SEND_FAILURE;
+ strStatus = "AuthStatus.SEND_FAILURE";
+ statusCode = 500;
+
+ } else if (servletName.contains(JASPICData.AUTHSTAT_SENDCONT_ND)) {
+ rval = AuthStatus.SEND_CONTINUE;
+ strStatus = "AuthStatus.SEND_CONTINUE";
+ statusCode = 401;
+
+ } else if (servletName.contains(JASPICData.AUTHSTAT_SENDSUCCESS_ND)) {
+ rval = AuthStatus.SEND_SUCCESS;
+ strStatus = "AuthStatus.SEND_SUCCESS";
+ statusCode = 200;
+
+ } else if (servletName.contains(JASPICData.AUTHSTAT_FAILURE_ND)) {
+ rval = AuthStatus.FAILURE;
+ strStatus = "AuthStatus.FAILURE";
+ statusCode = 500;
+
+ } else if (servletName.contains(JASPICData.AUTHSTAT_THROW_EX_ND)) {
+ msg += " returning AuthStatus=AuthException";
+ logger.log(INFO, msg);
+ throw new AuthException(msg);
+
+ } else if (servletName.contains(JASPICData.AUTHSTAT_SUCCESS_ND) || servletName.contains(JASPICData.AUTHSTAT_OPT_SUCCESS)
+ || servletName.contains(JASPICData.AUTHSTAT_MAND_SUCCESS)) {
+ rval = AuthStatus.SUCCESS;
+ strStatus = "AuthStatus.SUCCESS";
+ }
+
+ msg += " returning AuthStatus=" + strStatus;
+ logger.log(INFO, msg);
+
+ // lets get our response message in case we need to do something...
+ Object respObj = msgInfo.getResponseMessage();
+ HttpServletResponseWrapper response = null;
+ if (respObj != null) {
+ if (respObj instanceof HttpServletResponseWrapper) {
+ if (response != null) {
+ response.setStatus(statusCode);
+ msgInfo.setResponseMessage(response);
+ }
+ } else if (respObj instanceof HttpServletResponse) {
+ response = new HttpServletResponseWrapper((HttpServletResponse) respObj);
+ response.setStatus(statusCode);
+ msgInfo.setResponseMessage(response);
+ } else {
+ msg = "WARNING: we have some unidentified response object.";
+ logger.log(INFO, msg);
+ }
+ }
+
+ return rval;
+ }
+
+ /*
+ * This is a convenience method that will likely only be called once. Currently there is only one key to dump from the
+ * map, but his may change in the future.
+ */
+ private void dumpServletProfileKeys(MessageInfo msgInfo, String callerMethod) {
+ Map map = msgInfo.getMap();
+
+ // lets pull out some context info that we can use to help uniquely
+ // identify the source of this request
+ HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage();
+
+ String servletName = request.getServletPath();
+
+ // see assertion JASPI:SPEC:306 for details on this
+ // Jakarta Authentication states the following key must exist for servlet profile
+ if (map != null) {
+ Set keys = map.keySet();
+ Iterator iterator = keys.iterator();
+ while (iterator.hasNext()) {
+ Object oKey = iterator.next();
+ if (oKey instanceof String) {
+ String key = (String) oKey;
+ if (key != null) {
+ Object obj = map.get(key);
+ if (obj instanceof String) {
+ String keyVal = (String) map.get(key);
+ String msg = "dumpServletProfileKeys() called with attrs: ";
+ msg += " layer=" + JASPICData.LAYER_SERVLET;
+ msg += " servletName=" + servletName;
+ msg += " callerMethod=" + callerMethod;
+ msg += " key=" + key;
+
+ if (keyVal == null) {
+ msg += " value=NULL";
+ } else if (Boolean.valueOf(keyVal).booleanValue() == true) {
+ msg += " value=Valid";
+ } else {
+ msg += " value=Invalid value of: " + keyVal;
+ }
+ logger.log(INFO, msg);
+ } else {
+ logger.log(INFO, "Map key is of type :" + obj.getClass().getName());
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ private boolean isAuthMandatory(MessageInfo msgInfo) {
+ boolean bval = false;
+ Map map = msgInfo.getMap();
+
+ // lets pull out some context info that we can use to help uniquely
+ // identify the source of this request
+ HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage();
+
+ String servletName = request.getServletPath();
+
+ // see assertion JASPI:SPEC:306 for details on this
+ // jsr-196 states the following key must exist for servlet profile
+ String strKey = "jakarta.security.auth.message.MessagePolicy.isMandatory";
+ String msg;
+ if (map != null) {
+ String keyVal = (String) map.get(strKey);
+ msg = "isAuthMandatory() called with attrs: ";
+ msg += " layer=" + JASPICData.LAYER_SERVLET;
+ msg += " servletName=" + servletName;
+ msg += " key=" + strKey;
+
+ if (keyVal == null) {
+ msg += " value=NULL";
+ bval = false; // assume false if we cant determine
+ } else if (Boolean.valueOf(keyVal).booleanValue() == true) {
+ msg += " value=Valid";
+ bval = true;
+ } else {
+ // assume false
+ msg += " value=false";
+ bval = false;
+ }
+ logger.log(Level.FINE, msg);
+ } else {
+ msg = "FAILURE: No map in MessageInfo thus no key=" + strKey;
+ logger.log(Level.SEVERE, msg);
+ }
+
+ return bval;
+ }
+
+ /*
+ * Convenience method to dump messageInfo logging out.
+ */
+ private void logMessageTypes(MessageInfo messageInfo, String methodName) {
+ String msg;
+
+ String requestURI = "";
+
+ if (messageInfo != null) {
+ Object reqObj = messageInfo.getRequestMessage();
+ if (reqObj != null) {
+ // if here, we want to see if our reqObj is type HttpServletRequest
+ // and if so print out a log msg stating so.
+ // (Jakarta Authentication expects the reqObj to be type HttpServletRequest)
+ msg = methodName + ": MessageInfo.getRequestMessage() is of type ";
+ if (reqObj instanceof HttpServletRequest) {
+ msg = msg + "jakarta.servlet.http.HttpServletRequest";
+ requestURI = ((HttpServletRequest) reqObj).getRequestURI();
+
+ // related to assertion JASPI:SPEC:95 , this block of code
+ // may be needed if we need to identify which servlet invoked this
+ if (requestURI != null) {
+ // we want to know which servlet/jsp/html page generated
+ // this action and we want to include that in the log so we
+ // can check if the log gets generated for both servlets and
+ // for static html - which is a jsr-196 requirement.
+ String msg2 = msg + " for requestURI=" + requestURI;
+ logMsg(msg2);
+ }
+ } else {
+ msg = msg + messageInfo.getClass().getName();
+ }
+ logMsg(msg);
+ }
+
+ Object respObj = messageInfo.getResponseMessage();
+ if (respObj != null) {
+ // if here, we want to see if our respObj is type HttpServletResponse
+ // and if so print out a log msg stating so. (jsr-196 expects the
+ // respObj to be type HttpServletResponse)
+ msg = methodName + ": MessageInfo.getResponseMessage() is of type ";
+ if (respObj instanceof jakarta.servlet.http.HttpServletResponse) {
+ msg = msg + "jakarta.servlet.http.HttpServletResponse";
+ } else {
+ msg = msg + messageInfo.getClass().getName();
+ }
+ logMsg(msg);
+ }
+
+ } else {
+ msg = "TSServerAuthModule." + methodName + " called with null MessageInfo object.";
+ logMsg(msg);
+ }
+
+ }
+
+ /**
+ * Secure a service response before sending it to the client.
+ *
+ * This method is called to transform the response message acquired by calling getResponseMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. It may be used by the
+ * method implementation to retrieve Principals and credentials necessary to secure the response. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SEND_SUCCESS when the application response message was successfully secured. The secured response
+ * message may be obtained by calling by getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application response message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response (in the form of a request) from the peer.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by processing at least one additional request/response
+ * exchange (after having sent the response message returned in messageInfo).
+ *
+ * When this status value is returned, the application response must be saved by the authentication module such that it
+ * can be recovered when the module's validateRequest message is called to process the elicited response.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that a failure occured while securing the response message and that an
+ * appropriate failure response message is available by calling getResponseMeessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ logMsg("Enterred secureResponse");
+
+ String msg = "";
+ if (serviceSubject != null) {
+ msg = "TSServerAuthModule.secureResponse called with serviceSubject :" + getPrincipalNameFromSubject(serviceSubject);
+ } else {
+ msg = "TSServerAuthModule.secureResponse called with null service Subject";
+ }
+ logMsg(msg);
+
+ logMessageTypes(messageInfo, "secureResponse");
+ dumpServletProfileKeys(messageInfo, "secureResponse");
+
+ // verify that our context was not one that should have avoided a
+ // dispatch to service and thus should not have called secureResponse()
+ verifySecureResponseShouldHaveBeenCalled(messageInfo);
+
+ // help verify assertion: JASPIC:SPEC:108
+ setSpecialRequestAttribute(messageInfo, "secureRespCalled", "true");
+
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /*
+ * This is a specialized method used to set a request attribute that will be checked during the servlet/service
+ * invocation the idea is that secureResponse should not be called before the servlet/service invocation.
+ */
+ public void setSpecialRequestAttribute(MessageInfo msgInfo, String key, String value) {
+ String msg;
+
+ logMsg("TSServerAuthModule() setSpecialRequestAttribute called");
+
+ try {
+ // get request object
+ HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage();
+
+ // we want the servletpath here (not the context path) as this
+ // will give us a better idea which servlet was invoked
+ String servletName = request.getServletPath();
+
+ if ((servletName.contains(JASPICData.AUTHSTAT_MAND_SUCCESS))) {
+ // lets set our cts proprietary request attr indicating
+ // flow was in secureResponse
+ logMsg("setSpecialRequestAttribute() called for servlet: " + servletName);
+
+ request.setAttribute(key, value);
+ msgInfo.setRequestMessage(request);
+ logMsg("setSpecialRequestAttribute(): setAttribute() set for secureRespCalled=true");
+ }
+ } catch (Exception ex) {
+ // should not get here but in case, dump the ex and return true
+ msg = "Got Unexpected Exception!";
+ msg += " Exception message was: " + ex.toString();
+ logMsg(msg + "");
+ ex.printStackTrace();
+ }
+
+ }
+
+ public void verifySecureResponseShouldHaveBeenCalled(MessageInfo msgInfo) {
+ String msg;
+
+ try {
+ // get request object
+ HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage();
+
+ // we want the servletpath here (not the context path) as this
+ // will give us a better idea which servlet was invoked
+ String servletName = request.getServletPath();
+
+ if ((servletName.contains(JASPICData.AUTHSTAT_SENDFAILURE_ND)) || (servletName.contains(JASPICData.AUTHSTAT_SENDSUCCESS_ND))
+ || (servletName.contains(JASPICData.AUTHSTAT_FAILURE_ND)) || (servletName.contains(JASPICData.AUTHSTAT_THROW_EX_ND))
+ || (servletName.contains(JASPICData.AUTHSTAT_SUCCESS_ND))) {
+ // we have a specific context indicating we should NOT have been
+ // dispatched to a service (ie should not be in secureResponse)
+ msg = "FAILURE: should not have been dispatched to secureResponse";
+ logger.log(INFO, msg);
+ }
+ } catch (Exception ex) {
+ // should not get here but in case, dump the ex and return true
+ msg = "Got Unexpected Exception!";
+ msg += " Exception message was: " + ex.getMessage();
+ logger.log(INFO, msg);
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * Remove method specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSServerAuthModule.cleanSubject called");
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+ public String getPrincipalNameFromSubject(Subject subject) {
+ String concatPrincipalName = "";
+
+ for (Principal principal : subject.getPrincipals()) {
+ concatPrincipalName += principal.getName();
+ }
+
+ return concatPrincipalName;
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSServletWrapperSAM.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSServletWrapperSAM.java
new file mode 100644
index 0000000..095af3e
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/servlet/TSServletWrapperSAM.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.servlet;
+
+import static java.util.logging.Level.INFO;
+
+import ee.jakarta.tck.authentication.test.basic.sam.ServerCallbackSupport;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import jakarta.security.auth.message.module.ServerAuthModule;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+public class TSServletWrapperSAM implements ServerAuthModule {
+ private TSLogger logger;
+
+ private static CallbackHandler callbackHandler;
+
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ /**
+ * Creates a new instance of TSServletWrapperSAM
+ */
+ public TSServletWrapperSAM() {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ logMsg("TSServletWrapperSAM() constructor called");
+ }
+
+ public TSServletWrapperSAM(TSLogger log) {
+ if (log != null) {
+ logger = log;
+ } else {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ }
+ logMsg("TSServletWrapperSAM(TSLogger) constructor called");
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException {
+ if ((options != null) && options.get("TSLogger") != null) {
+ logger = (TSLogger) options.get("TSLogger");
+ }
+
+ callbackHandler = handler;
+
+ // perform some checking to support assertion JASPI:SPEC:87
+ verifyRequestPolicy(requestPolicy);
+
+ logger.log(INFO, "CBH for HttpServlet supports type: " + handler.getClass().getName());
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ doServerCallbackChecks(messageInfo, clientSubject, serviceSubject);
+
+ // Wrap the request - the resource to be invoked should get to see this
+ TSRequestWrapper tswrap = new TSRequestWrapper((HttpServletRequest) messageInfo.getRequestMessage());
+ tswrap.setOptionsMap(messageInfo.getMap());
+ messageInfo.setRequestMessage(tswrap);
+
+ // Wrap the response - the resource to be invoked should get to see this
+ messageInfo.setResponseMessage(new TSResponseWrapper((HttpServletResponse) messageInfo.getResponseMessage()));
+
+ return AuthStatus.SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+
+ // Unwrap the request
+ if (request instanceof TSRequestWrapper) {
+ messageInfo.setRequestMessage(((TSRequestWrapper) request).getRequest());
+ } else {
+ logMsg("Incorrect request type : " + request.getClass().getName());
+ }
+
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ if (response instanceof TSResponseWrapper) {
+ messageInfo.setResponseMessage(((TSResponseWrapper) response).getResponse());
+ } else {
+ logMsg("Incorrect response type : " + response.getClass().getName());
+ }
+
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /*
+ * This is a convenience method that will do some verification on the request policy to see if it complies with
+ * assertion JASPI:SPEC:87. If there are any problems found, appropriate log statements will be made and searched for
+ * later on in the Client code.
+ */
+ private void verifyRequestPolicy(MessagePolicy requestPolicy) {
+
+ String errStr = "Layer=" + JASPICData.LAYER_SERVLET;
+ errStr += " requestPolicy=invalid in TSServletWrapperSAM.initialize()";
+
+ if (requestPolicy == null) {
+ // we should never have a null requestpolicy here
+ logger.log(Level.SEVERE, errStr);
+ } else {
+ MessagePolicy.TargetPolicy[] tp = requestPolicy.getTargetPolicies();
+ if (tp.length < 1) {
+ // must return an array containing at least one TargetPolicy
+ logger.log(INFO, errStr);
+ } else {
+ for (int ii = 0; ii < tp.length; ii++) {
+ MessagePolicy.ProtectionPolicy pp = tp[ii].getProtectionPolicy();
+ if ((pp != null) && (!isProtectionPolicyIDValid(pp.getID()))) {
+ String str = "Layer=" + JASPICData.LAYER_SERVLET;
+ str += " Invalid ProtectionPolicy.getID()";
+ logger.log(INFO, str);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * (spec section 3.7.4) For servlet profile, calling the getID() method on the ProtectionPolicy must return one of the
+ * following values: ProtectionPolicy.AUTHENTICATE_SENDER ProtectionPolicy.AUTHENTICATE_CONTENT
+ */
+ public boolean isProtectionPolicyIDValid(String strId) {
+ boolean bval = false;
+
+ if ((strId.equals(MessagePolicy.ProtectionPolicy.AUTHENTICATE_CONTENT))
+ || (strId.equals(MessagePolicy.ProtectionPolicy.AUTHENTICATE_SENDER))) {
+ bval = true;
+ }
+
+ return bval;
+ }
+
+
+ /**
+ * Remove method specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSServletWrapperSAM.cleanSubject called");
+ subject = null;
+ }
+
+ private void logMsg(String str) {
+ if (logger != null) {
+ logger.log(INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+ private void doServerCallbackChecks(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ String servletPath = request.getContextPath() + request.getServletPath();
+ String msg = "";
+
+ ServerCallbackSupport serverCallbacks = new ServerCallbackSupport(logger, callbackHandler, JASPICData.LAYER_SERVLET, messageInfo,
+ clientSubject, serviceSubject);
+
+ // instead of calling all callbacks in one method, lets call them
+ // all individually so ithat we can check return values of each.
+ // serverCallbacks.verify();
+
+ if (serverCallbacks.verifyCPCCallback()) {
+ msg = "TSServletWrapperSAM.validateRequest(): verifyCPCCallback returned true";
+ } else {
+ msg = "TSServletWrapperSAM.validateRequest(): verifyCPCCallback returned false";
+ }
+ msg += " for servletPath = " + servletPath;
+ logMsg(msg);
+
+ if (serverCallbacks.verifyGPCCallback()) {
+ msg = "TSServletWrapperSAM.validateRequest(): verifyGPCCallback returned true";
+ } else {
+ msg = "TSServletWrapperSAM.validateRequest(): verifyGPCCallback returned false";
+ }
+ msg += " for servletPath = " + servletPath;
+ logMsg(msg);
+
+ if (serverCallbacks.verifyPVCCallback()) {
+ msg = "TSServletWrapperSAM.validateRequest(): verifyPVCCallback returned true";
+ } else {
+ msg = "TSServletWrapperSAM.validateRequest(): verifyPVCCallback returned false";
+ }
+ msg += " for servletPath = " + servletPath;
+ logMsg(msg);
+
+ return;
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/ClientCallbackSupport.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/ClientCallbackSupport.java
new file mode 100644
index 0000000..d1f4d6f
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/ClientCallbackSupport.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import java.io.IOException;
+import java.util.logging.Level;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class ClientCallbackSupport {
+ private static TSLogger logger;
+
+ private static CallbackHandler callbackHandler;
+
+ private static String profile;
+
+ private static final String runtimeType = "ClientRuntime";
+
+ /** Creates a new instance of ClientCallbackSupport */
+ public ClientCallbackSupport(TSLogger tsLogger, CallbackHandler cbkHandler, String profile) {
+ logger = tsLogger;
+ callbackHandler = cbkHandler;
+ this.profile = profile;
+ }
+
+ public boolean verify() {
+ try {
+ NameCallbackSupport();
+ PasswordCallbackSupport();
+ return true;
+
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ private void NameCallbackSupport() {
+ if (callbackHandler != null) {
+ try {
+ NameCallback nameCallback = new NameCallback("Please enter your name :", "j2ee");
+ nameCallback.setName("j2ee");
+
+ Callback[] callbacks = new Callback[] { nameCallback };
+
+ callbackHandler.handle(callbacks);
+ String returnedName = nameCallback.getName();
+
+ if (returnedName != null) {
+ logMsg("Name returned from Name Callback =" + returnedName);
+ }
+ logMsg("CallbackHandler supports NameCallback");
+ } catch (UnsupportedCallbackException usce) {
+ logMsg("CallbackHandler failed to support NameCallback :" + usce.getMessage());
+ usce.printStackTrace();
+ } catch (IOException ioe) {
+ logMsg("CallbackHandler failed to support NameCallback :" + ioe.getMessage());
+ ioe.printStackTrace();
+ }
+ }
+
+ }
+
+ private void PasswordCallbackSupport() {
+ if (callbackHandler != null) {
+ try {
+ PasswordCallback passwordCallback = new PasswordCallback("Please enter your password :", false);
+ passwordCallback.setPassword(new char[] { 'j', '2', 'e', 'e' });
+
+ Callback[] callbacks = new Callback[] { passwordCallback };
+
+ callbackHandler.handle(callbacks);
+ char returnedPassword[] = passwordCallback.getPassword();
+
+ if (returnedPassword != null) {
+ logMsg("Password returned from Password Callback =" + new String(returnedPassword));
+ }
+ logMsg("CallbackHandler supports PasswordCallback");
+ } catch (UnsupportedCallbackException usce) {
+ logMsg("CallbackHandler failed to support PasswordCallback :" + usce.getMessage());
+ usce.printStackTrace();
+ } catch (IOException ioe) {
+ logMsg("CallbackHandler failed to support PasswordCallback :" + ioe.getMessage());
+ ioe.printStackTrace();
+ }
+
+ }
+
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, "In " + profile + " : " + runtimeType + " " + str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSAuthExceptionClientAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSAuthExceptionClientAuthModule.java
new file mode 100644
index 0000000..86b947f
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSAuthExceptionClientAuthModule.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSAuthExceptionClientAuthModule implements jakarta.security.auth.message.module.ClientAuthModule {
+ private static TSLogger logger;
+
+ private static Map options;
+
+ /**
+ * Creates a new instance of ClientAuthModuleImpl
+ */
+ public TSAuthExceptionClientAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects where each element defines a message type supported by the module. A module should
+ * return an array containing at least one element. An empty array indicates that the module will attempt to support any
+ * message type. This method never returns null.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ Class[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ logMsg("TSAuthExceptionClientAuthModule.getSupportedMessageTypes called");
+ return classarray;
+ }
+
+ /**
+ * Secure a service request message before sending it to the service.
+ *
+ * This method is called to transform the request message acquired by calling getRequestMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to secure the request. If the Subject is
+ * not null, the method implementation may add additional Principals or credentials (pertaining to the source of the
+ * service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully secured. The secured request message may
+ * be obtained by calling by getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application request message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response from the peer security system. This status value
+ * also indicates that the application message has not yet been secured.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange after having received the security-specific response elicited by sending the security message.
+ *
+ * When this status value is returned, the corresponding invocation of validateResponse must be able to
+ * obtain the original application request message.
+ *
+ *
AuthStatus.FAILURE to indicate that a failure occured while securing the request message, and that an appropriate
+ * failure response message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
+ logMsg("TSAuthExceptionClientAuthModule.secureRequest called");
+ throw new AuthException("TSAuthExceptionClientAuthModule.secureRequest throws AuthException");
+ }
+
+ /**
+ * Validate a received service response.
+ *
+ * This method is called to transform the mechanism specific response message acquired by calling getResponseMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the response
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into the next mechanism specific request message to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the recipient of the service response, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the response. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application response message was successfully validated. The validated message is
+ * available by calling getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that response validation is incomplete, and that a continuation request was
+ * returned as the request message within messageInfo.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange.
+ *
+ *
AuthStatus.FAILURE to indicate that validation of the response failed, and that a failure response message has
+ * been established in messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ logMsg("TSAuthExceptionClientAuthModule.validateResponse called");
+
+ throw new AuthException("TSAuthExceptionClientAuthModule.validateResponse throws AuthException");
+
+ }
+
+ /**
+ * Remove implementation specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSAuthExceptionClientAuthModule.cleanSubject called");
+
+ // remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSAuthExceptionServerAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSAuthExceptionServerAuthModule.java
new file mode 100644
index 0000000..4a71c7f
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSAuthExceptionServerAuthModule.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import jakarta.security.auth.message.module.ServerAuthModule;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSAuthExceptionServerAuthModule implements ServerAuthModule {
+ private static TSLogger logger;
+
+ private static Map options;
+
+ /**
+ * Creates a new instance of TSAuthExceptionServerAuthModule
+ */
+ public TSAuthExceptionServerAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects, with at least one element defining a message type supported by the module.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ logMsg("TSAuthExceptionServerAuthModule.getSupportedMessageTypes called");
+ Class[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ return classarray;
+ }
+
+ /**
+ * Authenticate a received service request.
+ *
+ * This method is called to transform the mechanism specific request message acquired by calling getRequestMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the received
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into a corresponding mechanism specific response message, or to the validated application request message. The
+ * runtime will bind a validated application message into the the corresponding service invocation.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request. It is used by the method
+ * implementation to store Principals and credentials validated in the request.
+ *
+ * @param serviceSubject a Subject that represents the recipient of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the request. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully validated. The validated request message
+ * is available by calling getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_SUCCESS to indicate that validation/processing of the request message successfully produced the
+ * secured application response message (in messageInfo). The secured response message is available by calling
+ * getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that message validation is incomplete, and that a preliminary response was
+ * returned as the response message in messageInfo.
+ *
+ * When this status value is returned to challenge an application request message, the challenged request must be saved
+ * by the authentication module such that it can be recovered when the module's validateRequest message is called to
+ * process the request returned for the challenge.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that message validation failed and that an appropriate failure response
+ * message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ logMsg("TSAuthExceptionServerAuthModule.validateRequest called");
+
+ return AuthStatus.SUCCESS;
+ }
+
+ /**
+ * Secure a service response before sending it to the client.
+ *
+ * This method is called to transform the response message acquired by calling getResponseMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. It may be used by the
+ * method implementation to retrieve Principals and credentials necessary to secure the response. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SEND_SUCCESS when the application response message was successfully secured. The secured response
+ * message may be obtained by calling by getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application response message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response (in the form of a request) from the peer.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by processing at least one additional request/response
+ * exchange (after having sent the response message returned in messageInfo).
+ *
+ * When this status value is returned, the application response must be saved by the authentication module such that it
+ * can be recovered when the module's validateRequest message is called to process the elicited response.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that a failure occured while securing the response message and that an
+ * appropriate failure response message is available by calling getResponseMeessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ logMsg("TSAuthExceptionServerAuthModule.secureResponse called");
+
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /**
+ * Remove method specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSAuthExceptionServerAuthModule.cleanSubject called");
+
+ // Remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSClientAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSClientAuthModule.java
new file mode 100644
index 0000000..769b85d
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSClientAuthModule.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.basic.sam.CommonCallbackSupport;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import jakarta.security.auth.message.module.ClientAuthModule;
+import java.security.Principal;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSClientAuthModule implements ClientAuthModule {
+ private static TSLogger logger;
+
+ private static CallbackHandler callbackHandler;
+ private static Map options;
+
+ /**
+ * Creates a new instance of ClientAuthModuleImpl
+ */
+ public TSClientAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ callbackHandler = handler;
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects where each element defines a message type supported by the module. A module should
+ * return an array containing at least one element. An empty array indicates that the module will attempt to support any
+ * message type. This method never returns null.
+ */
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ Class>[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ logMsg("TSClientAuthModule.getSupportedMessageTypes called");
+
+ return classarray;
+ }
+
+ /**
+ * Secure a service request message before sending it to the service.
+ *
+ * This method is called to transform the request message acquired by calling getRequestMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to secure the request. If the Subject is
+ * not null, the method implementation may add additional Principals or credentials (pertaining to the source of the
+ * service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully secured. The secured request message may
+ * be obtained by calling by getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application request message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response from the peer security system. This status value
+ * also indicates that the application message has not yet been secured.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange after having received the security-specific response elicited by sending the security message.
+ *
+ * When this status value is returned, the corresponding invocation of validateResponse must be able to
+ * obtain the original application request message.
+ *
+ *
AuthStatus.FAILURE to indicate that a failure occured while securing the request message, and that an appropriate
+ * failure response message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
+
+ String msg = "";
+ if (clientSubject != null) {
+ msg = "TSClientAuthModule.secureRequest called with client Subject :" + getPrincipalNameFromSubject(clientSubject);
+ } else
+ msg = "TSClientAuthModule.secureRequest called with null client Subject";
+
+ logMsg(msg);
+ logMessageTypes(messageInfo, "secureRequest");
+
+ // Check Callback Handler support for SOAP Client runtime
+ ClientCallbackSupport clientCallbackSupport = new ClientCallbackSupport(logger, callbackHandler, "SOAP");
+
+ clientCallbackSupport.verify();
+
+ // Check CommonCallbacks support for SOAP client runtime
+ CommonCallbackSupport commonCallbacks = new CommonCallbackSupport(logger, callbackHandler, "SOAP", "ClientRuntime");
+
+ commonCallbacks.verify();
+
+ // Log the value for key jakarta.xml.ws.wsdl.service in messageInfoMap
+ Map messageInfoMap = messageInfo.getMap();
+
+ QName qName = (QName) messageInfoMap.get("jakarta.xml.ws.wsdl.service");
+
+ if (qName != null) {
+ String qNameToString = qName.toString();
+
+ msg = "TSClientAuthModule.secureRequest messageInfo :" + "jakarta.xml.ws.wsdl.service=" + qNameToString;
+ } else {
+ msg = "TSClientAuthModule.secureRequest messageInfo :"
+ + "** ERROR ** No value found for key jakarta.xml.ws.wsdl.service in MessageInfoMap" + " : Expected a QName";
+
+ }
+ logMsg(msg);
+
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /**
+ * Validate a received service response.
+ *
+ * This method is called to transform the mechanism specific response message acquired by calling getResponseMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the response
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into the next mechanism specific request message to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the recipient of the service response, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the response. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application response message was successfully validated. The validated message is
+ * available by calling getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that response validation is incomplete, and that a continuation request was
+ * returned as the request message within messageInfo.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange.
+ *
+ *
AuthStatus.FAILURE to indicate that validation of the response failed, and that a failure response message has
+ * been established in messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ String msg = "";
+ if (clientSubject != null) {
+ msg = "TSClientAuthModule.validateResponse called with client Subject :" + getPrincipalNameFromSubject(clientSubject);
+ } else
+ msg = "TSClientAuthModule.validateResponse called with null client Subject";
+
+ if (serviceSubject != null) {
+ msg = msg + " with serviceSubject :" + getPrincipalNameFromSubject(serviceSubject);
+ } else
+ msg = msg + " with null serviceSubject";
+
+ logMsg(msg);
+ logMessageTypes(messageInfo, "validateResponse");
+
+ // Log the value for key jakarta.xml.ws.wsdl.service in messageInfoMap
+ Map messageInfoMap = messageInfo.getMap();
+
+ QName qName = (QName) messageInfoMap.get("jakarta.xml.ws.wsdl.service");
+
+ if (qName != null) {
+ String qNameToString = qName.toString();
+
+ msg = "TSClientAuthModule.validateResponse messageInfo :" + "jakarta.xml.ws.wsdl.service=" + qNameToString;
+ } else {
+ msg = "TSClientAuthModule.validateResponse messageInfo :"
+ + "** ERROR ** No value found for key jakarta.xml.ws.wsdl.service in MessageInfoMap" + " : Expected a QName ";
+
+ }
+ logMsg(msg);
+
+ return AuthStatus.SUCCESS;
+ }
+
+ /**
+ * Remove implementation specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSClientAuthModule.cleanSubject called");
+
+ // remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+ private String getPrincipalNameFromSubject(Subject sub) {
+ String concatPrincipalName = "";
+
+ for (Principal principal : sub.getPrincipals()) {
+ concatPrincipalName += principal.getName();
+ }
+
+ return concatPrincipalName;
+ }
+
+ private void logMessageTypes(MessageInfo messageInfo, String methodName) {
+ String msg = null;
+
+ Object requestMessage = messageInfo.getRequestMessage();
+ Object responseMessage = messageInfo.getResponseMessage();
+
+ if (requestMessage != null) {
+ if (requestMessage instanceof jakarta.xml.soap.SOAPMessage) {
+ msg = methodName + " : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage";
+ logMsg(msg);
+ } else {
+ msg = methodName + " : MessageInfo.getRequestMessage() is of type " + requestMessage.getClass().getName();
+ logMsg(msg);
+
+ }
+ }
+
+ if (responseMessage != null) {
+ if (responseMessage instanceof jakarta.xml.soap.SOAPMessage) {
+ msg = methodName + " : MessageInfo.getResponseMessage() is of type jakarta.xml.soap.SOAPMessage";
+ logMsg(msg);
+ } else {
+ msg = methodName + " : MessageInfo.getResponseMessage() is of type " + responseMessage.getClass().getName();
+ logMsg(msg);
+
+ }
+ }
+
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSFailureClientAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSFailureClientAuthModule.java
new file mode 100644
index 0000000..ee2caa9
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSFailureClientAuthModule.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import jakarta.xml.soap.MessageFactory;
+import jakarta.xml.soap.SOAPBody;
+import jakarta.xml.soap.SOAPEnvelope;
+import jakarta.xml.soap.SOAPException;
+import jakarta.xml.soap.SOAPMessage;
+import jakarta.xml.soap.SOAPPart;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSFailureClientAuthModule implements jakarta.security.auth.message.module.ClientAuthModule {
+ private static TSLogger logger = null;
+
+ private static Map options = null;
+
+ /**
+ * Creates a new instance of ClientAuthModuleImpl
+ */
+ public TSFailureClientAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects where each element defines a message type supported by the module. A module should
+ * return an array containing at least one element. An empty array indicates that the module will attempt to support any
+ * message type. This method never returns null.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ Class[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ logMsg("TSFailureClientAuthModule.getSupportedMessageTypes called");
+ return classarray;
+ }
+
+ /**
+ * Secure a service request message before sending it to the service.
+ *
+ * This method is called to transform the request message acquired by calling getRequestMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to secure the request. If the Subject is
+ * not null, the method implementation may add additional Principals or credentials (pertaining to the source of the
+ * service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully secured. The secured request message may
+ * be obtained by calling by getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application request message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response from the peer security system. This status value
+ * also indicates that the application message has not yet been secured.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange after having received the security-specific response elicited by sending the security message.
+ *
+ * When this status value is returned, the corresponding invocation of validateResponse must be able to
+ * obtain the original application request message.
+ *
+ *
AuthStatus.FAILURE to indicate that a failure occured while securing the request message, and that an appropriate
+ * failure response message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
+
+ String msg = "TSFailureClientAuthModule.secureRequest called";
+ logMsg(msg);
+ SOAPMessage smsg = null;
+
+ try {
+
+ MessageFactory mf = MessageFactory.newInstance();
+ smsg = mf.createMessage();
+ if (smsg != null) {
+ setSOAPFault(smsg);
+ }
+
+ } catch (SOAPException ex) {
+ ex.printStackTrace();
+ }
+
+ // set the response message with SOAP Fault
+ messageInfo.setResponseMessage(smsg);
+
+ return AuthStatus.FAILURE;
+ }
+
+ /**
+ * Validate a received service response.
+ *
+ * This method is called to transform the mechanism specific response message acquired by calling getResponseMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the response
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into the next mechanism specific request message to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the recipient of the service response, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the response. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application response message was successfully validated. The validated message is
+ * available by calling getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that response validation is incomplete, and that a continuation request was
+ * returned as the request message within messageInfo.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange.
+ *
+ *
AuthStatus.FAILURE to indicate that validation of the response failed, and that a failure response message has
+ * been established in messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ String msg = "TSFailureClientAuthModule.validateResponse called";
+ logMsg(msg);
+
+ SOAPMessage smsg = (SOAPMessage) messageInfo.getResponseMessage();
+ if (smsg != null) {
+ setSOAPFault(smsg);
+ }
+
+ return AuthStatus.FAILURE;
+ }
+
+ /**
+ * Remove implementation specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSFailureClientAuthModule.cleanSubject called");
+
+ // remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+ private void setSOAPFault(SOAPMessage smsg) {
+ SOAPPart soap = smsg.getSOAPPart();
+ if (soap != null) {
+ try {
+ SOAPEnvelope envelope = soap.getEnvelope();
+ if (envelope != null) {
+ SOAPBody body = envelope.getBody();
+ if (body != null) {
+ QName qname = new QName("Client");
+ body.addFault(qname, "Error in Client");
+ }
+ }
+ } catch (SOAPException se) {
+ logger.log(Level.INFO, "Error adding SOAP Fault", se);
+
+ }
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSFailureServerAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSFailureServerAuthModule.java
new file mode 100644
index 0000000..937ab4b
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSFailureServerAuthModule.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSFailureServerAuthModule implements jakarta.security.auth.message.module.ServerAuthModule {
+ private static TSLogger logger;
+
+ private static Map options = null;
+
+ /**
+ * Creates a new instance of TSFailureServerAuthModule
+ */
+ public TSFailureServerAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects, with at least one element defining a message type supported by the module.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ logMsg("TSFailureServerAuthModule.getSupportedMessageTypes called");
+ Class[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ return classarray;
+ }
+
+ /**
+ * Authenticate a received service request.
+ *
+ * This method is called to transform the mechanism specific request message acquired by calling getRequestMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the received
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into a corresponding mechanism specific response message, or to the validated application request message. The
+ * runtime will bind a validated application message into the the corresponding service invocation.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request. It is used by the method
+ * implementation to store Principals and credentials validated in the request.
+ *
+ * @param serviceSubject a Subject that represents the recipient of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the request. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully validated. The validated request message
+ * is available by calling getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_SUCCESS to indicate that validation/processing of the request message successfully produced the
+ * secured application response message (in messageInfo). The secured response message is available by calling
+ * getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that message validation is incomplete, and that a preliminary response was
+ * returned as the response message in messageInfo.
+ *
+ * When this status value is returned to challenge an application request message, the challenged request must be saved
+ * by the authentication module such that it can be recovered when the module's validateRequest message is called to
+ * process the request returned for the challenge.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that message validation failed and that an appropriate failure response
+ * message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+
+ String msg = "TSFailureServerAuthModule.validateRequest called";
+ logMsg(msg);
+
+ return AuthStatus.SUCCESS;
+ }
+
+ /**
+ * Secure a service response before sending it to the client.
+ *
+ * This method is called to transform the response message acquired by calling getResponseMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. It may be used by the
+ * method implementation to retrieve Principals and credentials necessary to secure the response. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SEND_SUCCESS when the application response message was successfully secured. The secured response
+ * message may be obtained by calling by getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application response message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response (in the form of a request) from the peer.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by processing at least one additional request/response
+ * exchange (after having sent the response message returned in messageInfo).
+ *
+ * When this status value is returned, the application response must be saved by the authentication module such that it
+ * can be recovered when the module's validateRequest message is called to process the elicited response.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that a failure occured while securing the response message and that an
+ * appropriate failure response message is available by calling getResponseMeessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ String msg = "TSFailureServerAuthModule.secureResponse called";
+ logMsg(msg);
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /**
+ * Remove method specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSFailureServerAuthModule.cleanSubject called");
+ // remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendFailureClientAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendFailureClientAuthModule.java
new file mode 100644
index 0000000..0a8a6d4
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendFailureClientAuthModule.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import jakarta.xml.soap.SOAPBody;
+import jakarta.xml.soap.SOAPEnvelope;
+import jakarta.xml.soap.SOAPException;
+import jakarta.xml.soap.SOAPFault;
+import jakarta.xml.soap.SOAPMessage;
+import jakarta.xml.soap.SOAPPart;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSSendFailureClientAuthModule implements jakarta.security.auth.message.module.ClientAuthModule {
+ private static TSLogger logger = null;
+
+ private static Map options = null;
+
+ /**
+ * Creates a new instance of ClientAuthModuleImpl
+ */
+ public TSSendFailureClientAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects where each element defines a message type supported by the module. A module should
+ * return an array containing at least one element. An empty array indicates that the module will attempt to support any
+ * message type. This method never returns null.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ Class[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ logMsg("TSSendFailureClientAuthModule.getSupportedMessageTypes called");
+ return classarray;
+ }
+
+ /**
+ * Secure a service request message before sending it to the service.
+ *
+ * This method is called to transform the request message acquired by calling getRequestMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to secure the request. If the Subject is
+ * not null, the method implementation may add additional Principals or credentials (pertaining to the source of the
+ * service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully secured. The secured request message may
+ * be obtained by calling by getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application request message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response from the peer security system. This status value
+ * also indicates that the application message has not yet been secured.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange after having received the security-specific response elicited by sending the security message.
+ *
+ * When this status value is returned, the corresponding invocation of validateResponse must be able to
+ * obtain the original application request message.
+ *
+ *
AuthStatus.FAILURE to indicate that a failure occured while securing the request message, and that an appropriate
+ * failure response message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
+
+ String msg = "TSSendFailureClientAuthModule.secureRequest called";
+ logMsg(msg);
+
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /**
+ * Validate a received service response.
+ *
+ * This method is called to transform the mechanism specific response message acquired by calling getResponseMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the response
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into the next mechanism specific request message to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the recipient of the service response, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the response. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application response message was successfully validated. The validated message is
+ * available by calling getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that response validation is incomplete, and that a continuation request was
+ * returned as the request message within messageInfo.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange.
+ *
+ *
AuthStatus.FAILURE to indicate that validation of the response failed, and that a failure response message has
+ * been established in messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ String msg = "TSSendFailureClientAuthModule.validateResponse called";
+ logMsg(msg);
+
+ SOAPMessage smsg = (SOAPMessage) messageInfo.getResponseMessage();
+ String faultString = getSOAPFaultString(smsg);
+ if (faultString != null) {
+ msg = "TSSendFailureClientAuthModule.validateResponse received SOAPFault :" + faultString;
+ logMsg(msg);
+ }
+ return AuthStatus.SUCCESS;
+ }
+
+ /**
+ * Remove implementation specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSSendFailureClientAuthModule.cleanSubject called");
+
+ // remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+ private String getSOAPFaultString(SOAPMessage smsg) {
+ String faultString = null;
+ SOAPPart soap = smsg.getSOAPPart();
+ if (soap != null) {
+ try {
+ SOAPEnvelope envelope = soap.getEnvelope();
+ if (envelope != null) {
+ SOAPBody body = envelope.getBody();
+ if (body != null) {
+ if (body.hasFault()) {
+ SOAPFault sf = body.getFault();
+ faultString = sf.getFaultString();
+ }
+ }
+ }
+ } catch (SOAPException se) {
+ logger.log(Level.INFO, "Error adding SOAP Fault", se);
+
+ }
+ }
+ return faultString;
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendFailureServerAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendFailureServerAuthModule.java
new file mode 100644
index 0000000..5d74ace
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendFailureServerAuthModule.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import jakarta.xml.soap.MessageFactory;
+import jakarta.xml.soap.SOAPBody;
+import jakarta.xml.soap.SOAPEnvelope;
+import jakarta.xml.soap.SOAPException;
+import jakarta.xml.soap.SOAPMessage;
+import jakarta.xml.soap.SOAPPart;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSSendFailureServerAuthModule implements jakarta.security.auth.message.module.ServerAuthModule {
+ private static TSLogger logger = null;
+
+ private static Map options = null;
+
+ /**
+ * Creates a new instance of TSSendFailureServerAuthModule
+ */
+ public TSSendFailureServerAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects, with at least one element defining a message type supported by the module.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ logMsg("TSSendFailureServerAuthModule.getSupportedMessageTypes called");
+ Class[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ return classarray;
+ }
+
+ /**
+ * Authenticate a received service request.
+ *
+ * This method is called to transform the mechanism specific request message acquired by calling getRequestMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the received
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into a corresponding mechanism specific response message, or to the validated application request message. The
+ * runtime will bind a validated application message into the the corresponding service invocation.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request. It is used by the method
+ * implementation to store Principals and credentials validated in the request.
+ *
+ * @param serviceSubject a Subject that represents the recipient of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the request. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully validated. The validated request message
+ * is available by calling getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_SUCCESS to indicate that validation/processing of the request message successfully produced the
+ * secured application response message (in messageInfo). The secured response message is available by calling
+ * getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that message validation is incomplete, and that a preliminary response was
+ * returned as the response message in messageInfo.
+ *
+ * When this status value is returned to challenge an application request message, the challenged request must be saved
+ * by the authentication module such that it can be recovered when the module's validateRequest message is called to
+ * process the request returned for the challenge.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that message validation failed and that an appropriate failure response
+ * message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+
+ String msg = "TSSendFailureServerAuthModule.validateRequest called";
+ logMsg(msg);
+
+ SOAPMessage smsg = null;
+
+ try {
+
+ MessageFactory mf = MessageFactory.newInstance();
+ smsg = mf.createMessage();
+ if (smsg != null) {
+ setSOAPFault(smsg);
+ }
+
+ } catch (SOAPException ex) {
+ ex.printStackTrace();
+ }
+
+ // set the response message with SOAP Fault
+ messageInfo.setResponseMessage(smsg);
+
+ return AuthStatus.SEND_FAILURE;
+ }
+
+ /**
+ * Secure a service response before sending it to the client.
+ *
+ * This method is called to transform the response message acquired by calling getResponseMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. It may be used by the
+ * method implementation to retrieve Principals and credentials necessary to secure the response. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SEND_SUCCESS when the application response message was successfully secured. The secured response
+ * message may be obtained by calling by getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application response message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response (in the form of a request) from the peer.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by processing at least one additional request/response
+ * exchange (after having sent the response message returned in messageInfo).
+ *
+ * When this status value is returned, the application response must be saved by the authentication module such that it
+ * can be recovered when the module's validateRequest message is called to process the elicited response.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that a failure occured while securing the response message and that an
+ * appropriate failure response message is available by calling getResponseMeessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ String msg = "TSSendFailureServerAuthModule.secureResponse called";
+ logMsg(msg);
+
+ SOAPMessage smsg = null;
+
+ try {
+
+ MessageFactory mf = MessageFactory.newInstance();
+ smsg = mf.createMessage();
+ if (smsg != null) {
+ setSOAPFault(smsg);
+ }
+
+ } catch (SOAPException ex) {
+ ex.printStackTrace();
+ }
+
+ // set the response message with SOAP Fault
+ messageInfo.setResponseMessage(smsg);
+
+ return AuthStatus.SEND_FAILURE;
+ }
+
+ /**
+ * Remove method specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSSendFailureServerAuthModule.cleanSubject called");
+ // remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+ private void setSOAPFault(SOAPMessage smsg) {
+ SOAPPart soap = smsg.getSOAPPart();
+ if (soap != null) {
+ try {
+ SOAPEnvelope envelope = soap.getEnvelope();
+ if (envelope != null) {
+ SOAPBody body = envelope.getBody();
+ if (body != null) {
+ QName qname = new QName("Server");
+ body.addFault(qname, "Error in Server");
+
+ }
+ }
+ } catch (SOAPException se) {
+ logger.log(Level.INFO, "Error adding SOAP Fault", se);
+
+ }
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendSuccessClientAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendSuccessClientAuthModule.java
new file mode 100644
index 0000000..390f457
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendSuccessClientAuthModule.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSSendSuccessClientAuthModule implements jakarta.security.auth.message.module.ClientAuthModule {
+ private static TSLogger logger = null;
+
+ private static Map options = null;
+
+ /**
+ * Creates a new instance of ClientAuthModuleImpl
+ */
+ public TSSendSuccessClientAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects where each element defines a message type supported by the module. A module should
+ * return an array containing at least one element. An empty array indicates that the module will attempt to support any
+ * message type. This method never returns null.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ Class[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ logMsg("TSSendSuccessClientAuthModule.getSupportedMessageTypes called");
+ return classarray;
+ }
+
+ /**
+ * Secure a service request message before sending it to the service.
+ *
+ * This method is called to transform the request message acquired by calling getRequestMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to secure the request. If the Subject is
+ * not null, the method implementation may add additional Principals or credentials (pertaining to the source of the
+ * service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully secured. The secured request message may
+ * be obtained by calling by getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application request message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response from the peer security system. This status value
+ * also indicates that the application message has not yet been secured.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange after having received the security-specific response elicited by sending the security message.
+ *
+ * When this status value is returned, the corresponding invocation of validateResponse must be able to
+ * obtain the original application request message.
+ *
+ *
AuthStatus.FAILURE to indicate that a failure occured while securing the request message, and that an appropriate
+ * failure response message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
+
+ String msg = "TSSendSuccessClientAuthModule.secureRequest called";
+ logMsg(msg);
+
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /**
+ * Validate a received service response.
+ *
+ * This method is called to transform the mechanism specific response message acquired by calling getResponseMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the response
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into the next mechanism specific request message to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the recipient of the service response, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the response. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
AuthStatus.SUCCESS when the application response message was successfully validated. The validated message is
+ * available by calling getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that response validation is incomplete, and that a continuation request was
+ * returned as the request message within messageInfo.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by conducting at least one additional request/response
+ * exchange.
+ *
+ *
AuthStatus.FAILURE to indicate that validation of the response failed, and that a failure response message has
+ * been established in messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ String msg = "TSSendSuccessClientAuthModule.validateResponse called";
+ logMsg(msg);
+
+ return AuthStatus.SUCCESS;
+ }
+
+ /**
+ * Remove implementation specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSSendSuccessClientAuthModule.cleanSubject called");
+
+ // remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendSuccessServerAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendSuccessServerAuthModule.java
new file mode 100644
index 0000000..ac0bdd1
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSSendSuccessServerAuthModule.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSSendSuccessServerAuthModule implements jakarta.security.auth.message.module.ServerAuthModule {
+ private static TSLogger logger = null;
+
+ private static Map options = null;
+
+ /**
+ * Creates a new instance of TSSendSuccessServerAuthModule
+ */
+ public TSSendSuccessServerAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects, with at least one element defining a message type supported by the module.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ logMsg("TSSendSuccessServerAuthModule.getSupportedMessageTypes called");
+ Class[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ return classarray;
+ }
+
+ /**
+ * Authenticate a received service request.
+ *
+ * This method is called to transform the mechanism specific request message acquired by calling getRequestMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the received
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into a corresponding mechanism specific response message, or to the validated application request message. The
+ * runtime will bind a validated application message into the the corresponding service invocation.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request. It is used by the method
+ * implementation to store Principals and credentials validated in the request.
+ *
+ * @param serviceSubject a Subject that represents the recipient of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the request. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully validated. The validated request message
+ * is available by calling getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_SUCCESS to indicate that validation/processing of the request message successfully produced the
+ * secured application response message (in messageInfo). The secured response message is available by calling
+ * getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that message validation is incomplete, and that a preliminary response was
+ * returned as the response message in messageInfo.
+ *
+ * When this status value is returned to challenge an application request message, the challenged request must be saved
+ * by the authentication module such that it can be recovered when the module's validateRequest message is called to
+ * process the request returned for the challenge.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that message validation failed and that an appropriate failure response
+ * message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+
+ String msg = "TSSendSuccessServerAuthModule.validateRequest called";
+ logMsg(msg);
+
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /**
+ * Secure a service response before sending it to the client.
+ *
+ * This method is called to transform the response message acquired by calling getResponseMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. It may be used by the
+ * method implementation to retrieve Principals and credentials necessary to secure the response. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SEND_SUCCESS when the application response message was successfully secured. The secured response
+ * message may be obtained by calling by getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application response message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response (in the form of a request) from the peer.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by processing at least one additional request/response
+ * exchange (after having sent the response message returned in messageInfo).
+ *
+ * When this status value is returned, the application response must be saved by the authentication module such that it
+ * can be recovered when the module's validateRequest message is called to process the elicited response.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that a failure occured while securing the response message and that an
+ * appropriate failure response message is available by calling getResponseMeessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ String msg = "TSSendSuccessServerAuthModule.secureResponse called";
+ logMsg(msg);
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /**
+ * Remove method specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSSendSuccessServerAuthModule.cleanSubject called");
+ // remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSServerAuthModule.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSServerAuthModule.java
new file mode 100644
index 0000000..d3c5e41
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/module/soap/TSServerAuthModule.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.module.soap;
+
+import ee.jakarta.tck.authentication.test.basic.sam.CommonCallbackSupport;
+import ee.jakarta.tck.authentication.test.basic.sam.ServerCallbackSupport;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.security.auth.message.AuthException;
+import jakarta.security.auth.message.AuthStatus;
+import jakarta.security.auth.message.MessageInfo;
+import jakarta.security.auth.message.MessagePolicy;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class TSServerAuthModule implements jakarta.security.auth.message.module.ServerAuthModule {
+ private static TSLogger logger;
+
+ private static CallbackHandler callbackHandler;
+
+ private static Map options;
+
+ /**
+ * Creates a new instance of TSServerAuthModule
+ */
+ public TSServerAuthModule() {
+ }
+
+ /**
+ * Initialize this module with request and response message policies to enforce, a CallbackHandler, and any
+ * module-specific configuration properties.
+ *
+ *
+ * The request policy and the response policy must not both be null.
+ *
+ * @param requestPolicy the request policy this module must enforce, or null.
+ *
+ * @param responsePolicy the response policy this module must enforce, or null.
+ *
+ * @param handler CallbackHandler used to request information.
+ *
+ * @param options a Map of module-specific configuration properties.
+ *
+ * @exception AuthException if module initialization fails, including for the case where the options argument contains
+ * elements that are not supported by the module.
+ */
+ @Override
+ public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy, CallbackHandler handler, Map optns) throws AuthException {
+ callbackHandler = handler;
+ options = optns;
+
+ // Get the reference to TSLogger from the Map "options"
+ if (options.get("TSLogger") != null)
+ logger = (TSLogger) options.get("TSLogger");
+
+ }
+
+ /**
+ * Get the one or more Class objects representing the message types supported by the module.
+ *
+ * @return an array of Class objects, with at least one element defining a message type supported by the module.
+ */
+ @Override
+ public Class[] getSupportedMessageTypes() {
+ logMsg("TSServerAuthModule.getSupportedMessageTypes called");
+ Class[] classarray = { jakarta.xml.soap.SOAPMessage.class };
+ return classarray;
+ }
+
+ /**
+ * Authenticate a received service request.
+ *
+ * This method is called to transform the mechanism specific request message acquired by calling getRequestMessage (on
+ * messageInfo) into the validated application message to be returned to the message processing runtime. If the received
+ * message is a (mechanism specific) meta-message, the method implementation must attempt to transform the meta-message
+ * into a corresponding mechanism specific response message, or to the validated application request message. The
+ * runtime will bind a validated application message into the the corresponding service invocation.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param clientSubject a Subject that represents the source of the service request. It is used by the method
+ * implementation to store Principals and credentials validated in the request.
+ *
+ * @param serviceSubject a Subject that represents the recipient of the service request, or null. It may be used by the
+ * method implementation as the source of Principals or credentials to be used to validate the request. If the Subject
+ * is not null, the method implementation may add additional Principals or credentials (pertaining to the recipient of
+ * the service request) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SUCCESS when the application request message was successfully validated. The validated request message
+ * is available by calling getRequestMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_SUCCESS to indicate that validation/processing of the request message successfully produced the
+ * secured application response message (in messageInfo). The secured response message is available by calling
+ * getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that message validation is incomplete, and that a preliminary response was
+ * returned as the response message in messageInfo.
+ *
+ * When this status value is returned to challenge an application request message, the challenged request must be saved
+ * by the authentication module such that it can be recovered when the module's validateRequest message is called to
+ * process the request returned for the challenge.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that message validation failed and that an appropriate failure response
+ * message is available by calling getResponseMessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+
+ String msg = "";
+ if (clientSubject != null) {
+ msg = "TSServerAuthModule.validateRequest called with client Subject :" + getPrincipalNameFromSubject(clientSubject);
+ } else
+ msg = "TSClientAuthModule.validateRequest called with null client Subject";
+
+ if (serviceSubject != null) {
+ msg = msg + " with serviceSubject :" + getPrincipalNameFromSubject(serviceSubject);
+ } else
+ msg = msg + " with null serviceSubject";
+
+ logMsg(msg);
+ logMessageTypes(messageInfo, "validateRequest");
+
+ // Check Callback Handler support for Server runtime
+ ServerCallbackSupport serverCallbackSupport = new ServerCallbackSupport(logger, callbackHandler, "SOAP");
+
+ serverCallbackSupport.verify();
+
+ // Check common Callback support for SOAP server runtime
+ CommonCallbackSupport commonCallbacks = new CommonCallbackSupport(logger, callbackHandler, "SOAP", "ServerRuntime");
+
+ commonCallbacks.verify();
+
+ return AuthStatus.SUCCESS;
+ }
+
+ /**
+ * Secure a service response before sending it to the client.
+ *
+ * This method is called to transform the response message acquired by calling getResponseMessage (on messageInfo) into
+ * the mechanism specific form to be sent by the runtime.
+ *
+ * This method conveys the outcome of its message processing either by returning an AuthStatus value or by throwing an
+ * AuthException.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param serviceSubject a Subject that represents the source of the service response, or null. It may be used by the
+ * method implementation to retrieve Principals and credentials necessary to secure the response. If the Subject is not
+ * null, the method implementation may add additional Principals or credentials (pertaining to the source of the service
+ * response) to the Subject.
+ *
+ * @return an AuthStatus object representing the completion status of the processing performed by the method. The
+ * AuthStatus values that may be returned by this method are defined as follows:
+ *
+ *
+ *
AuthStatus.SEND_SUCCESS when the application response message was successfully secured. The secured response
+ * message may be obtained by calling by getResponseMessage on messageInfo.
+ *
+ *
AuthStatus.SEND_CONTINUE to indicate that the application response message (within messageInfo) was replaced with
+ * a security message that should elicit a security-specific response (in the form of a request) from the peer.
+ *
+ * This status value serves to inform the calling runtime that (in order to successfully complete the message exchange)
+ * it will need to be capable of continuing the message dialog by processing at least one additional request/response
+ * exchange (after having sent the response message returned in messageInfo).
+ *
+ * When this status value is returned, the application response must be saved by the authentication module such that it
+ * can be recovered when the module's validateRequest message is called to process the elicited response.
+ *
+ *
AuthStatus.SEND_FAILURE to indicate that a failure occured while securing the response message and that an
+ * appropriate failure response message is available by calling getResponseMeessage on messageInfo.
+ *
+ *
+ * @exception AuthException when the message processing failed without establishing a failure response message (in
+ * messageInfo).
+ */
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ String msg = "";
+ if (serviceSubject != null) {
+ msg = "TSServerAuthModule.secureResponse called with serviceSubject :" + getPrincipalNameFromSubject(serviceSubject);
+ } else
+ msg = "TSServerAuthModule.secureResponse called with null service Subject";
+
+ logMsg(msg);
+ logMessageTypes(messageInfo, "secureResponse");
+
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ /**
+ * Remove method specific principals and credentials from the subject.
+ *
+ * @param messageInfo a contextual object that encapsulates the client request and server response objects, and that may
+ * be used to save state across a sequence of calls made to the methods of this interface for the purpose of completing
+ * a secure message exchange.
+ *
+ * @param subject the Subject instance from which the Principals and credentials are to be removed.
+ *
+ * @exception AuthException if an error occurs during the Subject processing.
+ */
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ logMsg("TSServerAuthModule.cleanSubject called");
+ // remove the contents of the subject and return an empty subject
+ subject = null;
+ }
+
+ public void logMsg(String str) {
+ if (logger != null) {
+ logger.log(Level.INFO, str);
+ } else {
+ System.out.println("*** TSLogger Not Initialized properly ***");
+ System.out.println("*** TSSVLogMessage : ***" + str);
+ }
+ }
+
+ public String getPrincipalNameFromSubject(Subject sub) {
+ Principal principal = null;
+ String concatPrincipalName = "";
+ Set principalSet = sub.getPrincipals();
+
+ Iterator iterator = principalSet.iterator();
+ while (iterator.hasNext()) {
+ principal = (Principal) iterator.next();
+ concatPrincipalName += principal.getName();
+ }
+
+ return concatPrincipalName;
+ }
+
+ private void logMessageTypes(MessageInfo messageInfo, String methodName) {
+ String msg = null;
+
+ Object requestMessage = messageInfo.getRequestMessage();
+ Object responseMessage = messageInfo.getResponseMessage();
+
+ if (requestMessage != null) {
+ if (requestMessage instanceof jakarta.xml.soap.SOAPMessage) {
+ msg = methodName + " : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage";
+ logMsg(msg);
+ } else {
+ msg = methodName + " : MessageInfo.getRequestMessage() is of type " + requestMessage.getClass().getName();
+ logMsg(msg);
+
+ }
+ }
+
+ if (responseMessage != null) {
+ if (responseMessage instanceof jakarta.xml.soap.SOAPMessage) {
+ msg = methodName + " : MessageInfo.getResponseMessage() is of type jakarta.xml.soap.SOAPMessage";
+ logMsg(msg);
+ } else {
+ msg = methodName + " : MessageInfo.getResponseMessage() is of type " + responseMessage.getClass().getName();
+ logMsg(msg);
+
+ }
+ }
+
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/BASE64Decoder.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/BASE64Decoder.java
new file mode 100644
index 0000000..f233174
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/BASE64Decoder.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1995, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.util;
+
+import java.io.OutputStream;
+import java.io.PushbackInputStream;
+import java.io.PrintStream;
+
+/**
+ * This class implements a BASE64 Character decoder as specified in RFC1521.
+ *
+ * This RFC is part of the MIME specification which is published by the Internet
+ * Engineering Task Force (IETF). Unlike some other encoding schemes there is
+ * nothing in this encoding that tells the decoder where a buffer starts or
+ * stops, so to use it you will need to isolate your encoded data into a single
+ * chunk and then feed them this decoder. The simplest way to do that is to read
+ * all of the encoded data into a string and then use:
+ *
+ *
+ *
+ * This will decode the String in bufferString and give you an array of
+ * bytes in the array myData.
+ *
+ * On errors, this class throws a CEFormatException with the following detail
+ * strings:
+ *
+ *
+ * "BASE64Decoder: Not enough bytes for an atom."
+ *
+ *
+ * @author Chuck McManis
+ * @see CharacterEncoder
+ * @see BASE64Decoder
+ */
+
+public class BASE64Decoder extends CharacterDecoder {
+
+ /** This class has 4 bytes per atom */
+ protected int bytesPerAtom() {
+ return (4);
+ }
+
+ /** Any multiple of 4 will do, 72 might be common */
+ protected int bytesPerLine() {
+ return (72);
+ }
+
+ /**
+ * This character array provides the character to value map based on RFC1521.
+ */
+ private final static char pem_array[] = {
+ // 0 1 2 3 4 5 6 7
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 1
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 2
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 3
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 4
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 5
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 6
+ '4', '5', '6', '7', '8', '9', '+', '/' // 7
+ };
+
+ private final static byte pem_convert_array[] = new byte[256];
+
+ static {
+ for (int i = 0; i < 255; i++) {
+ pem_convert_array[i] = -1;
+ }
+ for (int i = 0; i < pem_array.length; i++) {
+ pem_convert_array[pem_array[i]] = (byte) i;
+ }
+ }
+
+ byte decode_buffer[] = new byte[4];
+
+ /**
+ * Decode one BASE64 atom into 1, 2, or 3 bytes of data.
+ */
+ protected void decodeAtom(PushbackInputStream inStream,
+ OutputStream outStream, int rem) throws java.io.IOException {
+ int i;
+ byte a = -1, b = -1, c = -1, d = -1;
+
+ if (rem < 2) {
+ throw new CEFormatException(
+ "BASE64Decoder: Not enough bytes for an atom.");
+ }
+ do {
+ i = inStream.read();
+ if (i == -1) {
+ throw new CEStreamExhausted();
+ }
+ } while (i == '\n' || i == '\r');
+ decode_buffer[0] = (byte) i;
+
+ i = readFully(inStream, decode_buffer, 1, rem - 1);
+ if (i == -1) {
+ throw new CEStreamExhausted();
+ }
+
+ if (rem > 3 && decode_buffer[3] == '=') {
+ rem = 3;
+ }
+ if (rem > 2 && decode_buffer[2] == '=') {
+ rem = 2;
+ }
+ switch (rem) {
+ case 4:
+ d = pem_convert_array[decode_buffer[3] & 0xff];
+ // NOBREAK
+ case 3:
+ c = pem_convert_array[decode_buffer[2] & 0xff];
+ // NOBREAK
+ case 2:
+ b = pem_convert_array[decode_buffer[1] & 0xff];
+ a = pem_convert_array[decode_buffer[0] & 0xff];
+ break;
+ }
+
+ switch (rem) {
+ case 2:
+ outStream.write((byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)));
+ break;
+ case 3:
+ outStream.write((byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)));
+ outStream.write((byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)));
+ break;
+ case 4:
+ outStream.write((byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)));
+ outStream.write((byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)));
+ outStream.write((byte) (((c << 6) & 0xc0) | (d & 0x3f)));
+ break;
+ }
+ return;
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/CEFormatException.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/CEFormatException.java
new file mode 100644
index 0000000..2a52316
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/CEFormatException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1995, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.util;
+
+import java.io.IOException;
+
+public class CEFormatException extends IOException {
+ public CEFormatException(String s) {
+ super(s);
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/CEStreamExhausted.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/CEStreamExhausted.java
new file mode 100644
index 0000000..f44dd79
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/CEStreamExhausted.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 1995, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.util;
+
+import java.io.IOException;
+
+/** This exception is thrown when EOF is reached */
+public class CEStreamExhausted extends IOException {
+};
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/CharacterDecoder.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/CharacterDecoder.java
new file mode 100644
index 0000000..d3ed788
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/sam/util/CharacterDecoder.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1995, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.sam.util;
+
+import java.io.OutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * This class defines the decoding half of character encoders. A character
+ * decoder is an algorithim for transforming 8 bit binary data that has been
+ * encoded into text by a character encoder, back into original binary form.
+ *
+ * The character encoders, in general, have been structured around a central
+ * theme that binary data can be encoded into text that has the form:
+ *
+ *
+ *
+ * Of course in the simplest encoding schemes, the buffer has no distinct prefix
+ * of suffix, however all have some fixed relationship between the text in an
+ * 'atom' and the binary data itself.
+ *
+ * In the CharacterEncoder and CharacterDecoder classes, one complete chunk of
+ * data is referred to as a buffer. Encoded buffers are all text, and
+ * decoded buffers (sometimes just referred to as buffers) are binary octets.
+ *
+ * To create a custom decoder, you must, at a minimum, overide three abstract
+ * methods in this class.
+ *
+ *
bytesPerAtom which tells the decoder how many bytes to expect from
+ * decodeAtom
+ *
decodeAtom which decodes the bytes sent to it as text.
+ *
bytesPerLine which tells the encoder the maximum number of bytes per
+ * line.
+ *
+ *
+ * In general, the character decoders return error in the form of a
+ * CEFormatException. The syntax of the detail string is
+ *
+ *
+ * DecoderClassName: Error message.
+ *
+ *
+ * Several useful decoders have already been written and are referenced in the
+ * See Also list below.
+ *
+ * @author Chuck McManis
+ * @see CEFormatException
+ * @see CharacterEncoder
+ * @see UCDecoder
+ * @see UUDecoder
+ * @see BASE64Decoder
+ */
+
+public abstract class CharacterDecoder {
+
+ /** Return the number of bytes per atom of decoding */
+ abstract protected int bytesPerAtom();
+
+ /** Return the maximum number of bytes that can be encoded per line */
+ abstract protected int bytesPerLine();
+
+ /** decode the beginning of the buffer, by default this is a NOP. */
+ protected void decodeBufferPrefix(PushbackInputStream aStream,
+ OutputStream bStream) throws IOException {
+ }
+
+ /** decode the buffer suffix, again by default it is a NOP. */
+ protected void decodeBufferSuffix(PushbackInputStream aStream,
+ OutputStream bStream) throws IOException {
+ }
+
+ /**
+ * This method should return, if it knows, the number of bytes that will be
+ * decoded. Many formats such as uuencoding provide this information. By
+ * default we return the maximum bytes that could have been encoded on the
+ * line.
+ */
+ protected int decodeLinePrefix(PushbackInputStream aStream,
+ OutputStream bStream) throws IOException {
+ return (bytesPerLine());
+ }
+
+ /**
+ * This method post processes the line, if there are error detection or
+ * correction codes in a line, they are generally processed by this method.
+ * The simplest version of this method looks for the (newline) character.
+ */
+ protected void decodeLineSuffix(PushbackInputStream aStream,
+ OutputStream bStream) throws IOException {
+ }
+
+ /**
+ * This method does an actual decode. It takes the decoded bytes and writes
+ * them to the OutputStream. The integer l tells the method how many
+ * bytes are required. This is always <= bytesPerAtom().
+ */
+ protected void decodeAtom(PushbackInputStream aStream, OutputStream bStream,
+ int l) throws IOException {
+ throw new CEStreamExhausted();
+ }
+
+ /**
+ * This method works around the bizarre semantics of BufferedInputStream's
+ * read method.
+ */
+ protected int readFully(InputStream in, byte buffer[], int offset, int len)
+ throws java.io.IOException {
+ for (int i = 0; i < len; i++) {
+ int q = in.read();
+ if (q == -1)
+ return ((i == 0) ? -1 : i);
+ buffer[i + offset] = (byte) q;
+ }
+ return len;
+ }
+
+ /**
+ * Decode the text from the InputStream and write the decoded octets to the
+ * OutputStream. This method runs until the stream is exhausted.
+ *
+ * @exception CEFormatException
+ * An error has occured while decoding
+ * @exception CEStreamExhausted
+ * The input stream is unexpectedly out of data
+ */
+ public void decodeBuffer(InputStream aStream, OutputStream bStream)
+ throws IOException {
+ int i;
+ int totalBytes = 0;
+
+ PushbackInputStream ps = new PushbackInputStream(aStream);
+ decodeBufferPrefix(ps, bStream);
+ while (true) {
+ int length;
+
+ try {
+ length = decodeLinePrefix(ps, bStream);
+ for (i = 0; (i + bytesPerAtom()) < length; i += bytesPerAtom()) {
+ decodeAtom(ps, bStream, bytesPerAtom());
+ totalBytes += bytesPerAtom();
+ }
+ if ((i + bytesPerAtom()) == length) {
+ decodeAtom(ps, bStream, bytesPerAtom());
+ totalBytes += bytesPerAtom();
+ } else {
+ decodeAtom(ps, bStream, length - i);
+ totalBytes += (length - i);
+ }
+ decodeLineSuffix(ps, bStream);
+ } catch (CEStreamExhausted e) {
+ break;
+ }
+ }
+ decodeBufferSuffix(ps, bStream);
+ }
+
+ /**
+ * Alternate decode interface that takes a String containing the encoded
+ * buffer and returns a byte array containing the data.
+ *
+ * @exception CEFormatException
+ * An error has occured while decoding
+ */
+ public byte decodeBuffer(String inputString)[] throws IOException {
+ byte inputBuffer[] = new byte[inputString.length()];
+ ByteArrayInputStream inStream;
+ ByteArrayOutputStream outStream;
+
+ inputString.getBytes(0, inputString.length(), inputBuffer, 0);
+ inStream = new ByteArrayInputStream(inputBuffer);
+ outStream = new ByteArrayOutputStream();
+ decodeBuffer(inStream, outStream);
+ return (outStream.toByteArray());
+ }
+
+ /**
+ * Decode the contents of the inputstream into a buffer.
+ */
+ public byte decodeBuffer(InputStream in)[] throws IOException {
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ decodeBuffer(in, outStream);
+ return (outStream.toByteArray());
+ }
+
+ /**
+ * Decode the contents of the String into a ByteBuffer.
+ */
+ public ByteBuffer decodeBufferToByteBuffer(String inputString)
+ throws IOException {
+ return ByteBuffer.wrap(decodeBuffer(inputString));
+ }
+
+ /**
+ * Decode the contents of the inputStream into a ByteBuffer.
+ */
+ public ByteBuffer decodeBufferToByteBuffer(InputStream in)
+ throws IOException {
+ return ByteBuffer.wrap(decodeBuffer(in));
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/CommonTests.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/CommonTests.java
new file mode 100644
index 0000000..ec7910a
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/CommonTests.java
@@ -0,0 +1,1409 @@
+/*
+ * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigFactoryForStandalone;
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigProviderStandalone;
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSRegistrationListener;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.AuthConfigProvider;
+import jakarta.security.auth.message.config.RegistrationListener;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * This contains generic methods/tests which are expected to be used by tests in each of the supported profiles (eg
+ * SERVLET, SOAP, Standalone, etc)
+ *
+ * @author Oracle
+ */
+public class CommonTests {
+ private static final String AuthConfigProviderClass = TSAuthConfigProviderStandalone.class.getName();
+ private static final String AuthConfigProviderLayer = "STANDALONE_LAYER";
+ private static final String AuthConfigProviderAppContext = "STANDALONE_CONTEXT";
+ private static final String AuthConfigProviderDesc = "Some description";
+
+ private PrintWriter out;
+
+ public CommonTests() {
+
+ }
+
+ public CommonTests(PrintWriter out) {
+ this.out = out;
+ }
+
+ public void setOut(PrintWriter out) {
+ this.out = out;
+ }
+
+ public PrintWriter getOut() {
+ return this.out;
+ }
+
+ /*
+ * this tests the following: - get current ACF - verify that removeRegistration(arg) will return FALSE when invalid arg
+ * supplied.
+ */
+ public void _ACF_testFactoryRemoveRegistration() throws Exception {
+ try {
+ // get current AuthConfigFactory
+ AuthConfigFactory authConfigFactory = AuthConfigFactory.getFactory();
+ if (authConfigFactory == null) {
+ // this could fail because the system can't
+ // find AuthConfigFactory (check for setting of -Djava.security.properties)
+ printIt("FAILURE - Could not get current AuthConfigFactory.");
+ throw new Exception("_ACF_testFactoryRemoveRegistration : FAILED");
+ }
+
+ // based on javadoc, calling removeRegistration with invalid registration
+ // must return false. It must NOT return true nor throw exception.
+ boolean rval = authConfigFactory.removeRegistration("SomePhakeRegistrationThatWontExist");
+
+ if (rval == true) {
+ printIt("FAILED: calling removeRegistration() on invalid registration returned true.");
+ throw new Exception("_ACF_testFactoryRemoveRegistration : FAILED");
+ }
+ } catch (Exception ex) {
+ printIt("FAILED: calling removeRegistration() with invalid registration threw exception.");
+ throw ex;
+ }
+
+ printIt("_ACF_testFactoryRemoveRegistration : passed");
+ }
+
+ /*
+ * this tests the following: - get current ACF - verify that getRegistrationIDs(acp) NEVER returns null hint: must
+ * return empty array even if unrecognized acp.
+ */
+ public void _ACF_testFactoryGetRegistrationIDs() throws Exception {
+ try {
+ // Get current AuthConfigFactory
+ AuthConfigFactory authConfigFactory = AuthConfigFactory.getFactory();
+ if (authConfigFactory == null) {
+ // This could fail because the system can't find AuthConfigFactory
+ // (check for setting of -Djava.security.properties)
+ printIt("FAILURE - Could not get current AuthConfigFactory.");
+ throw new Exception("_ACF_testFactoryGetRegistrationIDs : FAILED");
+ }
+
+ String[] registrationIDs = authConfigFactory.getRegistrationIDs(null);
+
+ if (registrationIDs == null) {
+ printIt("FAILED: calling getRegistrationIDs(null) returned null.");
+ throw new Exception("_ACF_testFactoryGetRegistrationIDs : FAILED");
+ }
+ } catch (Exception ex) {
+ printIt("FAILED: calling getRegistrationIDs(null) threw exception.");
+ throw ex;
+ }
+
+ printIt("_ACF_testFactoryGetRegistrationIDs : passed");
+ }
+
+ /*
+ * this tests the following: - get current ACF - verify getRegistrationContext(string) returns NULL for unrecognized
+ * string.
+ */
+ public void _ACF_testFactoryGetRegistrationContext() throws Exception {
+ try {
+ // get current AuthConfigFactory
+ AuthConfigFactory authConfigFactory = AuthConfigFactory.getFactory();
+ if (authConfigFactory == null) {
+ // This could fail due to permissions or because the system can't
+ // find ACF (check for setting of -Djava.security.properties)
+ printIt("FAILURE - Could not get current AuthConfigFactory.");
+ throw new Exception("_ACF_testFactoryGetRegistrationContext : FAILED");
+ }
+
+ AuthConfigFactory.RegistrationContext registrationContext =
+ authConfigFactory.getRegistrationContext("SomePhakeRegistrationThatWontExist");
+
+ if (registrationContext != null) {
+ printIt("FAILED: calling getRegistrationContext() on invalid context returned non-null.");
+ throw new Exception("_ACF_testFactoryGetRegistrationContext : FAILED");
+ }
+ } catch (Exception ex) {
+ printIt("FAILED: calling getRegistrationContext() with invalid registration threw exception.");
+ throw ex;
+ }
+
+ printIt("_ACF_testFactoryGetRegistrationContext : passed");
+ }
+
+ /*
+ * this tests the following: - get vendors ACF - verify detachListener() returns non-NULL for listener that is not found
+ * tied to ACP with the passed in layer & appContext. unrecognized string.
+ */
+ public void _ACF_testFactoryDetachListener(String vendorsClassName) throws Exception {
+
+ try {
+ // Change AuthConfigFactory to use vendors AuthConfigFactory instead of CTS AuthConfigFactory
+ printIt("getting Auth Config Factory for: " + vendorsClassName);
+ AuthConfigFactory vendorsAuthConfigFactory = CommonUtils.getAuthConfigFactory(vendorsClassName);
+ AuthConfigFactory.setFactory(vendorsAuthConfigFactory);
+ String vendorAuthConfigFactoryClass = vendorsAuthConfigFactory.getClass().getName();
+ printIt("vendorACFClass = " + vendorAuthConfigFactoryClass);
+
+ MyRegistrationListener listener = new MyRegistrationListener("phakeLayer", "phakeAppContext");
+ String[] listeners = vendorsAuthConfigFactory.detachListener(listener, "phakeLayer", "phakeAppContext");
+
+ if (listeners == null) {
+ // should NOT get here since we expect non-null returned...it may be
+ // empty but should never be null
+ printIt("FAILED: calling detachListener() on unfound listener returned null.");
+ throw new Exception("_ACF_testFactoryDetachListener : FAILED");
+ }
+ } catch (Exception ex) {
+ printIt("FAILED: calling detachListener() with unfound listener threw exception.");
+ throw ex;
+ } finally {
+ // restore original (CTS) factory class
+ CommonUtils.resetDefaultACF();
+ }
+
+ printIt("_ACF_testFactoryDetachListener : passed");
+ }
+
+ /*
+ * this tests the following: - get current (CTS default) ACF - switch ACF to use differetn (CTS) ACF - verify newly set
+ * ACF is correctly recognized (via getFactory() calls) - rest ACF back to (CTS default)default
+ */
+ public void _ACF_getFactory() throws Exception {
+ try {
+ // get current AuthConfigFactory
+ AuthConfigFactory currentAuthConfigFactory = AuthConfigFactory.getFactory();
+ if (currentAuthConfigFactory == null) {
+ // This could fail due to permissions or because the system can't
+ // find AuthConfigFactory (check for setting of -Djava.security.properties)
+ printIt("FAILURE - Could not get current AuthConfigFactory.");
+ throw new Exception("ACF_getFactory : FAILED");
+ }
+ String currentACFClass = currentAuthConfigFactory.getClass().getName();
+ printIt("ACF_getFactory.currentACFClass = " + currentACFClass);
+
+ // Set our AuthConfigFactory to a new/different AuthConfigFactory
+ TSAuthConfigFactoryForStandalone newAcf = new TSAuthConfigFactoryForStandalone();
+ AuthConfigFactory.setFactory(newAcf);
+ String newACFClass = newAcf.getClass().getName();
+ printIt("ACF_getFactory.newACFClass = " + newACFClass);
+
+ // verify our calls to getFactory() are getting the newly set factory
+ // instance and not the original ACF instance
+ AuthConfigFactory testAcf = AuthConfigFactory.getFactory();
+ if (testAcf == null) {
+ printIt("FAILURE - Could not get newly set AuthConfigFactory.");
+ throw new Exception("ACF_getFactory : FAILED");
+ }
+ String newlySetACFClass = testAcf.getClass().getName();
+ printIt("ACF_getFactory.newlySetACFClass = " + newlySetACFClass);
+
+ // Verify ACF's were set correctly
+ if (!newlySetACFClass.equals(newACFClass)) {
+ printIt("FAILURE - our current ACF does not match our newly set ACF");
+ throw new Exception("ACF_getFactory : FAILED");
+ } else {
+ String msg = "success - newlySetACFClass == newACFClass == " + newACFClass;
+ printIt(msg);
+ }
+
+ // restore original factory class
+ AuthConfigFactory.setFactory(currentAuthConfigFactory);
+
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory";
+ msg = msg + "or ACF.setFactory(). Check your server side security policies.";
+ printIt(msg);
+ ex.printStackTrace();
+ throw ex;
+ } catch (Exception ex) {
+ throw ex;
+ } finally {
+ // restore original (CTS) factory class
+ CommonUtils.resetDefaultACF();
+ }
+
+ printIt("ACF_getFactory : passed");
+ }
+
+ /*
+ * This is more comprehensive than ACF_getFactory as this tests the following: - get current (CTS default) ACF - verify
+ * we are starting with correct default - switch ACF to use different (CTS) ACF - verify newly set ACF is correctly
+ * recognized by checking a few different things (ACF factory classname, etc... - rest ACF back to (CTS default)default
+ */
+ public void _ACFSwitchFactorys(String vendorsClassName) throws Exception {
+
+ try {
+ // get current (CTS) AuthConfigFactory
+ AuthConfigFactory ctsAuthConfigFactory = AuthConfigFactory.getFactory();
+ if (ctsAuthConfigFactory == null) {
+ // This could fail because the system can't
+ // find AuthConfigFactory (check for setting of -Djava.security.properties)
+ printIt("FAILURE - Could not get current AuthConfigFactory.");
+ throw new Exception("ACFSwitchFactorys : FAILED");
+ }
+
+ // Verify we are starting with CTS AuthConfigFactory as the default AuthConfigFactory
+ String startingAuthConfigFactoryClass = ctsAuthConfigFactory.getClass().getName();
+ printIt("startingACFClass = " + startingAuthConfigFactoryClass);
+ if (!JASPICData.TSSV_ACF.equals(startingAuthConfigFactoryClass)) {
+ printIt("ERROR: we are not starting with expected default ACF class of: " + JASPICData.TSSV_ACF);
+ throw new Exception("ACFSwitchFactorys : FAILED");
+ }
+
+ // Change AuthConfigFactory to use vendors AuthConfigFactory instead of CTS AuthConfigFactory
+ printIt("getting Auth Config for: " + vendorsClassName);
+ AuthConfigFactory vendorsAuthConfigFactory = CommonUtils.getAuthConfigFactory(vendorsClassName);
+ AuthConfigFactory.setFactory(vendorsAuthConfigFactory);
+ String vendorAuthConfigFactoryClass = vendorsAuthConfigFactory.getClass().getName();
+ printIt("vendorACFClass = " + vendorAuthConfigFactoryClass);
+
+ // First verify we were able to change our AuthConfigFactory to use vendors
+ if (vendorAuthConfigFactoryClass.equals(JASPICData.TSSV_ACF)) {
+ // ohoh - nothing was changed we still have CTS default AuthConfigFactory
+ String str = "FAILURE - Could not set vendors AuthConfigFactory.";
+ printIt(str);
+ throw new Exception("ACFSwitchFactorys : FAILED");
+ }
+
+ // Next - verify our calls to getFactory() are getting a non-null factory
+ AuthConfigFactory testAuthConfigFactory = AuthConfigFactory.getFactory();
+ if (testAuthConfigFactory == null) {
+ String str = "FAILURE - Could not get vendors AuthConfigFactory.";
+ printIt(str);
+ throw new Exception("ACFSwitchFactorys : FAILED");
+ } else {
+ String str = "Successfully set vendors ACF.";
+ printIt(str);
+ }
+
+ String newlySetAuthConfigFactoryClass = testAuthConfigFactory.getClass().getName(); // should be
+ // confirming
+ // Impls ACF
+ printIt("newlySetACFClass = " + newlySetAuthConfigFactoryClass);
+
+ // next - verify getFactory() returns the expected/correct vendor class
+ // name
+ if (!newlySetAuthConfigFactoryClass.equals(vendorAuthConfigFactoryClass)) {
+ String str = "FAILURE - calling getFactory(). ";
+ str += "did not return expected/vendor ACF classname of: " + vendorAuthConfigFactoryClass;
+ printIt(str);
+ throw new Exception("ACFSwitchFactorys : FAILED");
+ } else {
+ String msg = "newlySetACFClass == vendorACFClass == " + vendorAuthConfigFactoryClass;
+ printIt(msg);
+ }
+
+ printIt("ACFSwitchFactorys : PASSED");
+ } catch (Exception ex) {
+ // unknown exception
+ String msg = "got unknown exception: " + ex.getMessage();
+ printIt(msg);
+ ex.printStackTrace();
+ throw ex;
+ } finally {
+ // restore original (CTS) factory class
+ CommonUtils.resetDefaultACF();
+ }
+
+ printIt("ACFSwitchFactorys : passed");
+ }
+
+ /*
+ * this tests that the ACF we currently expect is set to our CTS default ACF. The only way this should be, is if the
+ * runtime correctly read the ACF from the security files property of: authconfigprovider.factory
+ */
+ public void _testACFComesFromSecFile() throws Exception {
+
+ // verify our call to getFactory() gets the default ACF instance
+ AuthConfigFactory testAuthConfigFactory = AuthConfigFactory.getFactory();
+ if (testAuthConfigFactory == null) {
+ printIt("FAILURE - Could not get AuthConfigFactory.");
+ throw new Exception("testACFComesFromSecFile : FAILED");
+ }
+ String defaultAuthConfigFactoryClass = testAuthConfigFactory.getClass().getName();
+ printIt("testACFComesFromSecFile.defaultACFClass = " + defaultAuthConfigFactoryClass);
+
+ // Verify AuthConfigFactory matches the AuthConfigFactory that *should* exist in security prop file
+ if (!defaultAuthConfigFactoryClass.equals(JASPICData.TSSV_ACF)) {
+ printIt("FAILURE - our default ACF does not match our default ACF");
+ throw new Exception("testACFComesFromSecFile : FAILED");
+ }
+
+ printIt("testACFComesFromSecFile passed");
+ }
+
+ /*
+ * This is verifying that the invocation of removeRegistration() with an invalid and non-existant regId will return
+ * false. This assists with testing assertion JASPIC:SPEC:345
+ */
+ public void _ACFRemoveRegistrationWithBadId() {
+
+ try {
+ Random rand = new Random();
+
+ AuthConfigFactory acf = AuthConfigFactory.getFactory();
+
+ // create a unique registration Id
+ String uniqueRegId = "someMadeUpandNonExistantRegId";
+ uniqueRegId += String.valueOf(new Integer(rand.nextInt()).toString());
+ boolean bval = acf.removeRegistration(uniqueRegId);
+ if (bval == true) {
+ printIt("FAILURE - acf.removeRegistration(invalidId) returned true");
+ }
+ } catch (Exception ex) {
+ String str = "FAILURE - acf.removeRegistration(invalidId) exception msg: ";
+ str += ex.getMessage();
+ printIt(str);
+ ex.printStackTrace();
+ }
+
+ printIt("ACFRemoveRegistrationWithBadId passed");
+ }
+
+ /*
+ * private convenience method to check the description of the ACF's registrationContext.
+ */
+ private boolean verifyDescriptionSetOK(AuthConfigFactory authConfigFactory, String registrationId, String desc) {
+ boolean bval = false;
+ try {
+ AuthConfigFactory.RegistrationContext authConfigFactoryReg;
+ authConfigFactoryReg = authConfigFactory.getRegistrationContext(registrationId);
+ if ((authConfigFactoryReg != null) && (desc.equals(authConfigFactoryReg.getDescription()))) {
+ bval = true;
+ }
+ } catch (Exception ex) {
+ }
+
+ return bval;
+ }
+
+ /*
+ * This is one of our more comprehensive tests and it touches on several aspects of registration.
+ *
+ * This is used to test that we can register a provider using the two different ACF registerProvider() calls. (one call
+ * does persistent registration such that the registration will persist between jvm recycles but the other is an
+ * in-memory registration that will not persist between jvm recycles. The passed in arg: usePersistRegistration
+ * determines which registration method we are testing.
+ *
+ * This test does the following: - get current (CTS default) ACF - persistently register the CTS ACP's within *vendors*
+ * ACF - register a CTS provider (based on passed in arg of usePersistRegistration) in vendors ACF - JASPIC:SPEC:341 or
+ * JASPIC:SPEC:342 - verify our ACP registered okay - re-register the same ACP - verify re-registering ACP did NOT add
+ * another regId AND that the newly register ACP re-used same regID AND that the description also got replaced - per
+ * assertions of: JASPIC:SPEC:340 and JASPIC:SPEC:343 - unregister our CTS provider - restore CTS default ACF
+ *
+ */
+ public void _ACFRegisterOnlyOneACP(String logFileLocation, String providerConfigFilePath, String vendorAuthConfigFactoryClass,
+ boolean usePersistRegistration) throws Exception {
+
+ // (persistently) register providers in vendor factory
+ printIt("CommonTests._ACFRegisterOnlyOneACP(): logFileLocation = " + logFileLocation);
+ printIt("CommonTests._ACFRegisterOnlyOneACP(): providerConfigFilePath = " + providerConfigFilePath);
+ printIt("CommonTests._ACFRegisterOnlyOneACP(): vendorACFClass = " + vendorAuthConfigFactoryClass);
+
+ AuthConfigFactory vendorAuthConfigFactory = CommonUtils.register(logFileLocation, providerConfigFilePath,
+ vendorAuthConfigFactoryClass);
+ try {
+ if (vendorAuthConfigFactory == null) {
+ throw new Exception("Failed trying to register ACPs with vendors AuthConfigFactory");
+ }
+
+ // This is to ensure we do NOT have a previously registered standalone
+ // provider
+ // which could be due to a previously incomplete or faulty run. Also due
+ // to RI bug
+ // we have to add the provider, then remove it to ensure its not there.
+ // String clearId = CommonUtils.getRegisteredProviderID(AuthConfigProviderLayer,
+ // AuthConfigProviderAppContext, null);
+ String clearId = vendorAuthConfigFactory.registerConfigProvider(AuthConfigProviderClass, null, AuthConfigProviderLayer,
+ AuthConfigProviderAppContext, AuthConfigProviderDesc);
+ vendorAuthConfigFactory.removeRegistration(clearId);
+
+ // get the list of vendor registered provider ID's
+ String[] origRegIDs = vendorAuthConfigFactory.getRegistrationIDs(null);
+ int defaultLength = origRegIDs.length;
+
+ // Dump registered provider info - befor we try to add another ACP
+ printIt("Dumping providers which should only contain those in ProviderConfiguration.xml");
+ CommonUtils.dumpProviders(vendorAuthConfigFactory, origRegIDs);
+
+ // try to register a standalone provider for the 1st time
+ String regID1 = null;
+ if (usePersistRegistration) {
+ // use persistent reigstration - JASPIC:SPEC:341
+ regID1 = vendorAuthConfigFactory.registerConfigProvider(AuthConfigProviderClass, null, AuthConfigProviderLayer,
+ AuthConfigProviderAppContext, AuthConfigProviderDesc);
+ } else {
+ // use in-memory (ie non-persistent) registration - JASPIC:SPEC:342
+ regID1 = vendorAuthConfigFactory.registerConfigProvider(null, AuthConfigProviderLayer, AuthConfigProviderAppContext,
+ AuthConfigProviderDesc);
+ }
+
+ String[] firstRegIDs = vendorAuthConfigFactory.getRegistrationIDs(null);
+ // now dump registered provider info - after adding 1 more ACP
+ printIt("Dumping providers which should show a newly added standalone provider.");
+ CommonUtils.dumpProviders(vendorAuthConfigFactory, firstRegIDs);
+
+ // verify that our 1st attempt at adding the an ACP did register ok
+ if ((regID1 == null) || (firstRegIDs.length <= defaultLength)) {
+ printIt("regID1 = " + regID1);
+ printIt("firstRegIDs.length = " + firstRegIDs.length + " defaultLength = " + defaultLength);
+ String err = "Could not register provider in vendors ACF class.";
+ err += " Problematic provider = " + AuthConfigProviderClass;
+ throw new Exception(err);
+ } else {
+ printIt("a new entry was registered");
+ }
+
+ // try to re-register the same standalone provider
+ // note: we have different description - which is okay
+ // this tests JASPIC:SPEC:340 / JASPIC:SPEC:343
+ String changedDesc = "some other description";
+ String regID2 = null;
+ if (usePersistRegistration) {
+ // use persistent registration
+ regID2 = vendorAuthConfigFactory.registerConfigProvider(AuthConfigProviderClass, null, AuthConfigProviderLayer,
+ AuthConfigProviderAppContext, changedDesc);
+ } else {
+ // use in-memory (ie non-persistent) registration
+ regID2 = vendorAuthConfigFactory.registerConfigProvider(null, AuthConfigProviderLayer, AuthConfigProviderAppContext,
+ changedDesc);
+ }
+
+ String[] secondRegIDs = vendorAuthConfigFactory.getRegistrationIDs(null);
+ // now dump registered provider info - after re-adding the same ACP
+ String msg = "Dumping providers which should show the standalone ";
+ msg += "provider with slighly different description.";
+ printIt(msg);
+ CommonUtils.dumpProviders(vendorAuthConfigFactory, secondRegIDs);
+
+ // verify that our 2nd attempt at adding the same ACP correctly replaced
+ // the
+ // same provider (based on appcontext and msg layer) and did NOT add
+ // another entry
+ if ((regID2 == null) || (firstRegIDs.length != secondRegIDs.length)) {
+ String err = "Failure during re-registering of ACP.";
+ err += " Attempts to re-register should replace the provider not add more copies of it.";
+ err += " Problematic provider = " + AuthConfigProviderClass;
+ throw new Exception(err);
+ } else {
+ printIt("the re-registered provider was replaced.");
+ }
+
+ // per assertion JASPIC:SPEC:340/JASPIC:SPEC:343 - regID1 and regID2 MUST
+ // be the same after a re-registering
+ // of same ACP based on javadoc reference for registerConfigProvider
+ if (!regID1.equals(regID2)) {
+ printIt("regID1 = " + regID1 + " regID2 = " + regID2);
+ String err = "Failure during re-registering of ACP - regID was invalid.";
+ err += " During a re-registration, the registration ID must be the same";
+ throw new Exception(err);
+ }
+
+ // verify our re-registered provider did replace the ACP and the
+ // Description
+ // (per assertion JASPIC:SPEC:340 / JASPIC:SPEC:343)
+ if (!verifyDescriptionSetOK(vendorAuthConfigFactory, regID2, changedDesc)) {
+ String err = "Failure during verification of ACP re-registration related ";
+ err += "to description overwrite";
+ throw new Exception(err);
+ }
+
+ // unregister our standalone provider -
+ vendorAuthConfigFactory.removeRegistration(regID2);
+
+ String[] finalRegIDs = vendorAuthConfigFactory.getRegistrationIDs(null);
+ // now dump registered provider info - after re-adding the same ACP
+ printIt("Dumping providers which should show only providers from ProviderConfiguration.xml.");
+ CommonUtils.dumpProviders(vendorAuthConfigFactory, finalRegIDs);
+
+ } catch (Exception ex) {
+ throw ex;
+ } finally {
+ // restore original (CTS) factory class
+ CommonUtils.resetDefaultACF();
+ }
+
+ printIt("AuthConfigFactory ACFRegisterOnlyOneACP passed");
+ }
+
+ /*
+ * this tests the ability to unregister a provider. First, it must register a provider, then once registered, the
+ * ability to unregister is then tested.
+ */
+ public void _ACFUnregisterACP(String logFileLocation, String providerConfigFilePath, String vendorACFClass) throws Exception {
+ try {
+ // register providers in vendor factory
+ AuthConfigFactory vendorACF = CommonUtils.register(logFileLocation, providerConfigFilePath, vendorACFClass);
+ if (vendorACF == null) {
+ throw new Exception("Failed trying to register ACPs with vendors ACF");
+ }
+
+ // get list of vendors registered provider ID's
+ String[] origRegIDs = vendorACF.getRegistrationIDs(null);
+
+ // dump registered provider info - befor we try to register a provider
+ printIt("Dumping providers from ProviderConfiguration.xml.");
+ CommonUtils.dumpProviders(vendorACF, origRegIDs);
+
+ // try to register a standalone provider for the 1st time
+ String regID1 = vendorACF.registerConfigProvider(null, AuthConfigProviderLayer, AuthConfigProviderAppContext,
+ AuthConfigProviderDesc);
+
+ String[] firstRegIDs = vendorACF.getRegistrationIDs(null);
+ // now dump registered provider info - after registering a provider
+ printIt("Dumping providers to show that a provider was added.");
+ CommonUtils.dumpProviders(vendorACF, firstRegIDs);
+
+ // verify that our 1st attempt at adding the an ACP did register ok
+ if ((regID1 == null) || (firstRegIDs.length <= origRegIDs.length)) {
+ printIt("regID1 = " + regID1);
+ printIt("firstRegIDs.length = " + firstRegIDs.length + " origRegIDs.length = " + origRegIDs.length);
+ String err = "Error registering provider in vendors ACF class.";
+ err += " Problematic provider = " + AuthConfigProviderClass;
+ throw new Exception(err);
+ } else {
+ printIt("a new entry was registered");
+ }
+
+ // now unregister our standalone provider
+ boolean wasFound = vendorACF.removeRegistration(regID1);
+
+ String[] finalRegIDs = vendorACF.getRegistrationIDs(null);
+ // now dump provider info - after unregistering provider
+ printIt("Dumping providers to only show providers in ProviderConfiguration.xml.");
+ CommonUtils.dumpProviders(vendorACF, finalRegIDs);
+
+ // verify removeRegistration returned proper boolean
+ if (!wasFound) {
+ String err = "ERROR: removeRegistration could not find the regID to remove.";
+ throw new Exception(err);
+ } else {
+ printIt("removeRegistration found the regID to remove");
+ }
+
+ // verify registry has proper number of items in it
+ if (finalRegIDs.length >= firstRegIDs.length) {
+ String err = "ERROR: removeRegistration had issue removing registry entry.";
+ throw new Exception(err);
+ }
+
+ // verify we can't access our regId anymore since it should be
+ // unregistered
+ if (true == vendorACF.removeRegistration(regID1)) {
+ String err = "ERROR: removeRegistration still thinks regID is valid but it should not be";
+ throw new Exception(err);
+ }
+ } catch (Exception ex) {
+ throw ex;
+ } finally {
+ // restore original (CTS) factory class
+ CommonUtils.resetDefaultACF();
+ }
+
+ printIt("AuthConfigFactory ACFRegisterOnlyOneACP passed");
+ }
+
+ /*
+ * basic registration test to verify we can register the CTS providers within the vendors ACF. (registration is
+ * persistent rgistration)
+ */
+ public void _AuthConfigFactoryRegistration(String logFileLocation, String providerConfigFilePath, String vendorACFClass)
+ throws Exception {
+
+ try {
+ // get default ACF being used
+ AuthConfigFactory defaultACF = AuthConfigFactory.getFactory();
+ String defaultACFClass = defaultACF.getClass().getName();
+ printIt("ACFUnregisterACP.defaultACFClass = " + defaultACFClass);
+
+ // register providers in vendor factory
+ AuthConfigFactory vendorACF = CommonUtils.register(logFileLocation, providerConfigFilePath, vendorACFClass);
+
+ if (vendorACF == null) {
+ throw new Exception("Failed trying to register ACPs with vendors ACF");
+ }
+
+ printIt("vendorACFClass = " + vendorACFClass);
+
+ // first verify we were able to change our ACF to use vendors
+ if (vendorACFClass.equals(JASPICData.TSSV_ACF)) {
+ // ohoh - nothing was changed we still have CTS default ACF
+ String str = "FAILURE - Could not set vendors AuthConfigFactory.";
+ printIt(str);
+ throw new Exception("AuthConfigFactoryRegistration : FAILED");
+ }
+
+ } catch (Exception ex) {
+ throw ex;
+ } finally {
+ // restore original (CTS) factory class
+ CommonUtils.resetDefaultACF();
+ }
+
+ printIt("AuthConfigFactoryRegistration passed");
+ }
+
+ /*
+ * This will test the ability to get the config provider when there are combos of null layers or app contexts. This
+ * should return the provider for the specified app context and null layer. This will also verify the ability to
+ * register provider a provider that has non-null appcontext and null layer with a listener. Then a verification that
+ * the notification works okay is done.
+ *
+ * Precedence rules are as follows:
+ *
+ * 1 - The provider specifically registered for the values passed as the layer and
+ * appContext arguments shall be selected.
+ *
+ * 2 - If no provider is selected according to the preceding rule, the provider
+ * specifically registered for the value passed as the appContext argument and for all (that is, null) layers shall be
+ * selected.
+ *
+ * 3 - If no provider is selected according to the preceding rules, the provider specifically registered for
+ * the value passed as the layer argument and for all (that is, null) appContexts shall be selected.
+ *
+ * 4 - If no provider
+ * is selected according to the preceding rules, the provider registered for all (that is, null) layers and for all
+ * (that is, null) appContexts shall be selected.
+ *
+ * 5 - If no provider is selected according to the preceding rules, the
+ * factory shall terminate its search for a registered provider.
+ *
+ */
+ public void _ACFTestPrecedenceRules(String vendorACFClass, boolean isPersistent) throws Exception {
+
+ String layers[] = { null, "phakeMsgLayer1" };
+ String contexts[] = { null, "ctxt1" };
+ AuthConfigFactory authConfigFactory = null;
+ String regId = null;
+ String[] regIds = new String[layers.length * contexts.length];
+
+ try {
+ if (vendorACFClass != null) {
+ authConfigFactory = CommonUtils.getAuthConfigFactory(vendorACFClass);
+ } else {
+ // error - we need valid vendor acf
+ throw new Exception("ACFTestPrecedenceRules : FAILED");
+ }
+
+ /*
+ * loop thru and create/register a new acp for each of the msglayer/appcontext combinations. Verify that the call to
+ * getConfigProvider() returns appropriate vals - even for case of null msg layer or null appcontext.
+ */
+ String description = "acp1";
+ int count = 0;
+ for (String layer : layers) {
+ for (String context : contexts) {
+ if (isPersistent) {
+ // Do persistent registration
+ regId = authConfigFactory.registerConfigProvider(
+ AuthConfigProviderClass,
+ null,
+ layer,
+ context,
+ description);
+ } else {
+ // Do in-memory registration
+ regId = authConfigFactory.registerConfigProvider(
+ new TSAuthConfigProviderStandalone((Map) null, null, null, description),
+ layer,
+ context,
+ description);
+ }
+
+ printIt("regId=" + regId + " for layer=" + layer + " " + " ctxt=" + context);
+
+ // Test precedence rule 1
+ boolean okay = testPrecedenceRule1(authConfigFactory, regId, layer, context, description);
+ if (!okay) {
+ printIt("Failed getConfiProvider() precedence rule 1.");
+ throw new Exception("ACFTestPrecedenceRules : FAILED");
+ }
+
+ regIds[count] = regId;
+ count++;
+ }
+ }
+
+ // test precedence rule 2
+ // This is when only specifying appContext and null layer
+ // which should return all matching appContexts
+ boolean okay = testPrecedenceRule2(authConfigFactory, isPersistent);
+ if (!okay) {
+ printIt("Failed getConfiProvider() precedence rule 2.");
+ throw new Exception("ACFTestPrecedenceRules : FAILED");
+ }
+
+ // test precedence rule 3
+ // This is when only specifying msgLayer and null appContext
+ // which should return the provider registered with that msgLayer
+ okay = testPrecedenceRule3(authConfigFactory, isPersistent);
+ if (!okay) {
+ printIt("Failed getConfiProvider() precedence rule 3.");
+ throw new Exception("ACFTestPrecedenceRules : FAILED");
+ }
+
+ // test precedence rule 4
+ // This is when we are trying to retrieve a registered acp
+ // that does not have matching context or layer - in which case
+ // acp registered with null layer and null context should be
+ // returned - if there was an acp registered with null/null)
+ okay = testPrecedenceRule4(authConfigFactory, isPersistent);
+ if (!okay) {
+ printIt("Failed getConfiProvider() precedence rule 4.");
+ throw new Exception("ACFTestPrecedenceRules : FAILED");
+ }
+
+ // cleanup ACPs that we registered in this method
+ okay = removeRegisteredACPs(authConfigFactory, regIds);
+ if (!okay) {
+ // we expect to get warning about unregistering ACPs here
+ printIt("Okay to ignore previous WARNING from call to removeRegisteredACPs");
+ }
+
+ // test precedence rule 5
+ // This is when we are trying to call getCOnfigProvider()
+ // with non-registered layer/context values.
+ // This verifies that no providers could be found and
+ // so factory must terminate its search for registerd acp.
+ okay = testPrecedenceRule5(authConfigFactory, isPersistent);
+ if (!okay) {
+ printIt("Failed getConfiProvider() precedence rule 5.");
+ throw new Exception("ACFTestPrecedenceRules : FAILED");
+ }
+
+ } catch (Exception ex) {
+ throw ex;
+ } finally {
+ // restore original (CTS) factory class
+ CommonUtils.resetDefaultACF();
+ }
+
+ printIt("ACFTestPrecedenceRules passed");
+ }
+
+ /*
+ * test is verifying we can get the correct provider back with the specifying of a non-existing msg layuer and context
+ */
+ private boolean testPrecedenceRule5(AuthConfigFactory acf, boolean isPersistent) throws Exception {
+ boolean rval = true;
+ String MSG_LAYER = "phakeMsgLayer5"; // non-existant msg layer
+ String APP_CTXT = "phakeContext5"; // non-existant context
+
+ AuthConfigProvider gottenAcp = acf.getConfigProvider(MSG_LAYER, APP_CTXT, null);
+ if (gottenAcp != null) {
+ printIt("Error - precedence rule 5 failure");
+ String str = ((TSAuthConfigProviderStandalone) gottenAcp).getDescription();
+ printIt("ERROR - precedence rule 5 returned acp desc = " + str);
+ rval = false;
+ }
+
+ return rval;
+ }
+
+ /*
+ * This will register two ACP's using same class but differ layer and contexts. One acp with have null/null and the
+ * other acp will have non-null layer/context. This then verifies it gets the correct ACP back (based on description).
+ */
+ private boolean testPrecedenceRule4(AuthConfigFactory acf, boolean isPersistent) throws Exception {
+ boolean rval = true;
+ TSAuthConfigProviderStandalone acp4, acp4b;
+ acp4 = new TSAuthConfigProviderStandalone((Map) null, null, null, "acp4");
+ acp4b = new TSAuthConfigProviderStandalone((Map) null, null, null, "acp4b");
+ String layer = null;
+ String context = null;
+ String layer2 = "layer4";
+ String context2 = "context 4";
+ String rId1 = null, rId2 = null;
+ Map props;
+ String strDesc1 = "acp4";
+ String strDesc2 = "acp4b";
+
+ if (isPersistent) {
+ // do persistent registration
+ props = setDescriptionProp(strDesc1);
+ rId1 = acf.registerConfigProvider(AuthConfigProviderClass, props, layer, context, strDesc1);
+ props = setDescriptionProp(strDesc2);
+ rId2 = acf.registerConfigProvider(AuthConfigProviderClass, props, layer2, context2, strDesc2);
+ } else {
+ // do in-memory registration
+ rId1 = acf.registerConfigProvider(acp4, layer, context, strDesc1);
+ rId2 = acf.registerConfigProvider(acp4b, layer2, context2, strDesc2);
+ }
+
+ AuthConfigProvider gottenAcp = acf.getConfigProvider(layer, context, null);
+ if (gottenAcp == null) {
+ printIt("Error - precedence rule 4 failure");
+ return false;
+ }
+
+ // make sure we get back provider registerd with null/null
+ AuthConfigFactory.RegistrationContext rc = acf.getRegistrationContext(rId1);
+ String str = rc.getDescription();
+ String str2 = ((TSAuthConfigProviderStandalone) gottenAcp).getDescription();
+ boolean bMatch = (str != null) && (str.equals(strDesc1)) && (str2 != null) && (str2.equals(strDesc1));
+ if (!bMatch) {
+ String err = "ERROR - precedence rule 4 returned wrong acp";
+ err += " rc.getDescription() = " + str + "gottenAcp.desc=" + str2;
+ printIt(err);
+ rval = false;
+ }
+
+ // also - test calling with invalid layer/context gets the provider
+ // that was registered with null layer and null context
+ // This should return provider registered with null/null
+ AuthConfigProvider gottenAcp2 = acf.getConfigProvider("nonExistantLayer", "nonExistantContext", null);
+ if (gottenAcp2 == null) {
+ printIt("Error - precedence rule 4b failure");
+ rval = false;
+ }
+
+ // since gottenAcp2 should have returned the provider that was
+ // registered with null/null which should have desc = strDesc1
+ if (gottenAcp2 != null) {
+ str = ((TSAuthConfigProviderStandalone) gottenAcp2).getDescription();
+ } else {
+ String err = "ERROR - unexpected null ACP encountered. (gottenAcp2 == null)";
+ printIt(err);
+ rval = false;
+ }
+
+ // call to getRegContext should return desc that corresponds
+ // to the acp we registered with rId2
+ rc = acf.getRegistrationContext(rId2);
+ str2 = rc.getDescription(); // should match strDesc2
+
+ bMatch = (str2 != null) && (str2.equals(strDesc2)) && (str != null) && (str.equals(strDesc1));
+ if (!bMatch) {
+ String err = "ERROR - precedence rule 4 (2nd check) returned wrong acp";
+ err += " rc.getDescription() = " + str2 + "gottenAcp2.description=" + str;
+ printIt(err);
+ rval = false;
+ }
+
+ // do some cleanup
+ acf.removeRegistration(rId1);
+ acf.removeRegistration(rId2);
+
+ return rval;
+ }
+
+ /*
+ * test is verifying we can get the correct provider back with the specifying of the unique msg layer and null/no
+ * appContext.
+ */
+ private boolean testPrecedenceRule3(AuthConfigFactory acf, boolean isPersistent) throws Exception {
+ boolean rval = true;
+ TSAuthConfigProviderStandalone acp3, acp3a;
+ String MSG_LAYER = "phakeMsgLayer1"; // unique msg layer
+ String APP_CTXT = "context3";
+ String rId = null;
+ String rId2 = null;
+ Map props;
+ String strDesc1 = "acp3";
+ String strDesc2 = "acp3a";
+
+ acp3 = new TSAuthConfigProviderStandalone((Map) null, null, null, strDesc1);
+ acp3a = new TSAuthConfigProviderStandalone((Map) null, null, null, strDesc2);
+
+ if (isPersistent) {
+ // do persistent registration
+ props = setDescriptionProp(strDesc1);
+ rId = acf.registerConfigProvider(AuthConfigProviderClass, props, MSG_LAYER, null, strDesc1);
+ props = setDescriptionProp(strDesc2);
+ rId2 = acf.registerConfigProvider(AuthConfigProviderClass, props, MSG_LAYER, APP_CTXT, strDesc2);
+ } else {
+ // do in-memory registration
+ rId = acf.registerConfigProvider(acp3, MSG_LAYER, null, strDesc1);
+ rId2 = acf.registerConfigProvider(acp3a, MSG_LAYER, APP_CTXT, strDesc2);
+ }
+
+ // we should get back acp registered with matching layer and null appcontext
+ AuthConfigProvider gottenAcp = acf.getConfigProvider(MSG_LAYER, null, null);
+ if (gottenAcp == null) {
+ printIt("Error - precedence rule 3 failure");
+ return false;
+ }
+
+ // make sure we didnt accidentally get back wrong provider
+ // we should get back acp with description = strDesc1
+ AuthConfigFactory.RegistrationContext rc = acf.getRegistrationContext(rId);
+ String str = rc.getDescription();
+ String str2 = ((TSAuthConfigProviderStandalone) gottenAcp).getDescription();
+ boolean bMatch = (str != null) && (str.equals(strDesc1)) && (str2 != null) && (str2.equals(strDesc1));
+ if (!bMatch) {
+ printIt("ERROR - precedence rule 3 returned wrong acp");
+ rval = false;
+ }
+
+ // do some cleanup
+ acf.removeRegistration(rId);
+ acf.removeRegistration(rId2);
+
+ return rval;
+ }
+
+ /*
+ * This verifies we can get the correct provider back with the specifying of the unique appContext and null/no msglayer.
+ */
+ private boolean testPrecedenceRule2(AuthConfigFactory acf, boolean isPersistent) throws Exception {
+ boolean rval = true;
+ TSAuthConfigProviderStandalone acp2, acp2a;
+ String rId = null;
+ String rId2 = null;
+ Map props;
+ String strDesc1 = "acp2";
+ String strDesc2 = "acp2a";
+
+ acp2 = new TSAuthConfigProviderStandalone((Map) null, null, null, strDesc1);
+ acp2a = new TSAuthConfigProviderStandalone((Map) null, null, null, strDesc2);
+
+ if (isPersistent) {
+ // do persistent registration
+ props = setDescriptionProp(strDesc1);
+ rId = acf.registerConfigProvider(AuthConfigProviderClass, props, null, "ctxt2", strDesc1);
+ props = setDescriptionProp(strDesc2);
+ rId2 = acf.registerConfigProvider(AuthConfigProviderClass, props, "nonexistLayer", "ctxt2", strDesc2);
+ } else {
+ // do in-memory registration
+ rId = acf.registerConfigProvider(acp2, null, "ctxt2", strDesc1);
+ rId2 = acf.registerConfigProvider(acp2a, "nonexistLayer", "ctxt2", strDesc2);
+ }
+
+ AuthConfigProvider gottenAcp = acf.getConfigProvider(null, "ctxt2", null);
+ if (gottenAcp == null) {
+ printIt("Error - precedence rule 2 failure");
+ return false;
+ }
+
+ // make sure we didnt accidentally get back wrong provider (where strDesc1
+ // is description for correct acp and anything else is wrong acp
+ AuthConfigFactory.RegistrationContext rc = acf.getRegistrationContext(rId);
+ String str = rc.getDescription();
+ String str2 = ((TSAuthConfigProviderStandalone) gottenAcp).getDescription();
+ boolean bMatch = (str != null) && (str.equals(strDesc1)) && (str2 != null) && (str2.equals(strDesc1));
+ if (!bMatch) {
+ String err = "ERROR - precedence rule 2 returned wrong acp ";
+ err += " rc.getDescription()= " + str;
+ err += " gottenAcp.getDescription()=" + str2;
+ printIt(err);
+ rval = false;
+ }
+
+ // do some cleanup
+ acf.removeRegistration(rId);
+ acf.removeRegistration(rId2);
+
+ return rval;
+ }
+
+ private boolean testPrecedenceRule1(AuthConfigFactory acf, String regId, String layer, String context, String desc) throws Exception {
+ boolean rval = true;
+
+ AuthConfigProvider gottenAcp;
+ gottenAcp = acf.getConfigProvider(layer, context, null);
+ if (gottenAcp == null) {
+ printIt("Error - no ACP found in call to getConfigProvider() with layer=" + layer + "and context=" + context);
+ rval = false;
+ } else {
+ AuthConfigFactory.RegistrationContext rc;
+ rc = acf.getRegistrationContext(regId);
+ String str = rc.getDescription();
+ boolean bMatch = (str != null) && (str.equals(desc));
+ if (!bMatch) {
+ printIt("ERROR getConfigProvider() returned wrong acp=" + str);
+ rval = false;
+ }
+
+ // next, confirm the getConfigProvider() above returned a valid
+ // regId that matches current layer & context info
+ boolean ok = verifyGetConfigProvider(acf, gottenAcp, regId, layer, context);
+ if (!ok) {
+ printIt("ERROR no registration found for regIds=" + regId);
+ rval = false;
+ }
+ }
+
+ return rval;
+ }
+
+ /*
+ * This is a convenience method that sets a property which can be used by the TSAuthConfigProviderStandalone class which
+ * looks for this property during instantiation by a persistent registration. Said differently, we use this property to
+ * set the description when we are creating a new/persistent ACP registration.
+ */
+ private Map setDescriptionProp(String val) {
+ HashMap props = new HashMap<>();
+ props.put(TSAuthConfigProviderStandalone.DESC_KEY, val);
+ return props;
+ }
+
+ /*
+ * This is used to verify the RegistrationContext value for isPersistent() matches what we expect to be set.
+ *
+ */
+ public boolean verifyRegContextPersitentVal(AuthConfigFactory acf, String regId, boolean expectedPersistent) throws Exception {
+ boolean rval = false;
+
+ AuthConfigFactory.RegistrationContext rc;
+ rc = acf.getRegistrationContext(regId);
+
+ if (rc == null) {
+ // error - cant find context for regId but should be able to
+ printIt("ERROR could not get RegistrationContext in verifyRegContextPersitentVal");
+ return false;
+ }
+
+ if (rc.isPersistent() == expectedPersistent) {
+ rval = true;
+ }
+
+ return rval;
+ }
+
+ /*
+ * This is used to verify that the passed in regId contains the expected msg layer and appcontext values. It also
+ * verifies that the passed in regId corresponds with the passed in acp.
+ */
+ public boolean verifyGetConfigProvider(AuthConfigFactory acf, AuthConfigProvider acp, String regId, String expectedLayer,
+ String expectedContext) throws Exception {
+ boolean rval = true;
+ boolean bLayer = false;
+ boolean bContext = false;
+
+ AuthConfigFactory.RegistrationContext rc;
+ rc = acf.getRegistrationContext(regId);
+
+ if (rc == null) {
+ // error - cant find context for regId but should be able to
+ printIt("ERROR could not get RegistrationContext in verifyGetConfigProvider");
+ return false;
+ }
+
+ if (((expectedLayer != null) && expectedLayer.equals(rc.getMessageLayer()))
+ || ((expectedLayer == null) && (rc.getMessageLayer() == null))) {
+ bLayer = true;
+ }
+
+ if (((expectedContext != null) && expectedContext.equals(rc.getAppContext()))
+ || ((expectedContext == null) && (rc.getAppContext() == null))) {
+ bContext = true;
+ }
+
+ // make sure our regId is registered for our acp
+ String[] regIds = acf.getRegistrationIDs(acp);
+ boolean regIdMatch = false;
+ for (int ii = 0; ii < regIds.length; ii++) {
+ if ((regId != null) && (regId.equals(regIds[ii]))) {
+ regIdMatch = true;
+ }
+ }
+
+ if (bLayer && bContext && regIdMatch) {
+ rval = true;
+ }
+
+ return rval;
+ }
+
+ /*
+ * This will test the ability to notify listeners for acps that are registered with a combo of profile layers and app
+ * contexts. This assists with testing: JASPIC:SPEC:336, JASPIC:SPEC:338, JASPIC:SPEC:339, JASPIC:SPEC:344,
+ * JASPIC:SPEC:337
+ */
+ public void _ACFTestNotifyOnUnReg(String vendorACFClass, boolean isPersistent) throws Exception {
+
+ String profileLayer[] = { null, "HttpServlet", "phakeProfile" };
+ String context[] = { null, "ctxt2", "ctxt3" };
+ AuthConfigFactory acf = null;
+
+ try {
+ if (vendorACFClass != null) {
+ acf = CommonUtils.getAuthConfigFactory(vendorACFClass);
+ } else {
+ // error - we need valid vendor acf
+ throw new Exception("ACFTestNotifyOnUnReg : FAILED");
+ }
+
+ // create/register new providers for each layer-context combination
+ String[] regIds = createAndRegisterACPs(acf, isPersistent, profileLayer, context);
+
+ // add listeners for each layer-context combo to ACPs - JASPIC:SPEC:337
+ TSRegistrationListener tlistener[] = addListenersToACP(acf, profileLayer, context);
+
+ // at this point, our listeners likely have not have been called,
+ // but to be sure - lets reset our listeners 'notified' flag
+ for (int ii = 0; ii < tlistener.length; ii++) {
+ tlistener[ii].resetNotifyFlag();
+ }
+
+ // assert JASPIC:SPEC:344
+ // remove registered ACPs using the passed in list of regIds. This
+ // must generate notifications to listeners associated with those ACPs
+ boolean ok = removeRegisteredACPs(acf, regIds);
+ if (!ok) {
+ // one of registered ids could not be found and/or unregistered
+ throw new Exception("ACFTestNotifyOnUnReg : FAILED");
+ }
+
+ // verify notifications occurred during unregistration JASPIC:SPEC:338
+ ok = verifyNotifications(acf, tlistener, profileLayer, context);
+ if (!ok) {
+ throw new Exception("ACFTestNotifyOnUnReg : FAILED");
+ }
+
+ // do some cleanup and verify if it went okay
+ ok = detachAllListeners(acf, tlistener, profileLayer, context);
+ if (!ok) {
+ // got error during detach
+ throw new Exception("ACFTestNotifyOnUnReg : FAILED");
+ }
+
+ } catch (Exception ex) {
+ throw ex;
+ } finally {
+ // restore original (CTS) factory class
+ CommonUtils.resetDefaultACF();
+ }
+ printIt("ACFTestNotifyOnUnReg passed");
+ }
+
+ /*
+ * This verifies notifications for the combinations of passed in layer and contexts. returns false if an error is
+ * encountered.
+ */
+ public boolean verifyNotifications(AuthConfigFactory acf, TSRegistrationListener[] tlistener, String[] layer, String[] context)
+ throws Exception {
+ boolean bval = true;
+
+ // verify notifications occurred during unregistration
+ for (int kk = 0; kk < tlistener.length; kk++) {
+ for (int ii = 0; ii < layer.length; ii++) {
+ for (int jj = 0; jj < context.length; jj++) {
+ boolean bPassed = false;
+ bPassed = tlistener[kk].check(layer[ii], context[jj]);
+ String str = "layer=" + layer[ii] + " and context=" + context[jj];
+ if (!bPassed) {
+ printIt(" Failed listener for: " + str);
+ bval = false;
+ }
+ }
+ }
+ }
+
+ return bval;
+ }
+
+ /*
+ * This detaches all listeners and also checks that the call to detachListenre never returns null. used in testing
+ * assert JASPIC:SPEC:339 returns false if an error is encountered.
+ */
+ public boolean detachAllListeners(AuthConfigFactory acf, TSRegistrationListener[] tlistener, String[] layer, String[] context)
+ throws Exception {
+ boolean bval = true;
+
+ for (int kk = 0; kk < tlistener.length; kk++) {
+ for (int ii = 0; ii < layer.length; ii++) {
+ for (int jj = 0; jj < context.length; jj++) {
+ // now, detach listeners
+ String rval[] = acf.detachListener(tlistener[kk], layer[ii], context[jj]);
+ if (rval == null) {
+ // should NEVER be null (per api doc)
+ String str = "layer=" + layer[ii] + " and context=" + context[jj];
+ printIt("Failed detachListener for: " + str);
+ bval = false;
+ }
+ }
+ }
+ }
+
+ return bval;
+ }
+
+ /*
+ * This takes the passed in list or ACP regIds and unregisteres those ACp's from the passed in ACF. This returns false
+ * if a registration is deemed invalid and cant be removed.
+ */
+ public boolean removeRegisteredACPs(AuthConfigFactory acf, String[] regIds) throws Exception {
+
+ boolean bval = true;
+
+ // remove registrations with listeners - should call notify on listeners
+ for (int ii = 0; ii < regIds.length; ii++) {
+ printIt(" REMOVING PROVIDERS TO INVOKE NOTIFY() for regId=" + regIds[ii]);
+ boolean result = false;
+
+ result = acf.removeRegistration(regIds[ii]);
+ if (!result) {
+ printIt("WARNING: no registration found for regIds=" + regIds[ii]);
+ bval = false;
+ }
+ }
+
+ return bval;
+ }
+
+ /*
+ * This method will create new listeners for the passed in layer/context combinations. After creating each listener, it
+ * is added to the ACP that matches the context/layer for that new listener. This returns an array or newly created
+ * listeners that were added to ACP's.
+ */
+ public TSRegistrationListener[] addListenersToACP(AuthConfigFactory acf, String[] layer, String[] context) throws Exception {
+
+ int theSize = layer.length * context.length; // num listeners
+ TSRegistrationListener[] tlistener = new TSRegistrationListener[theSize];
+ AuthConfigProvider tmpAcp[] = new AuthConfigProvider[theSize];
+
+ // Create listeners, then add them to ACPs
+ int count = 0;
+ for (int ii = 0; ii < layer.length; ii++) {
+ for (int jj = 0; jj < context.length; jj++) {
+ tlistener[count] = new TSRegistrationListener(layer[ii], context[jj]);
+ tmpAcp[ii] = acf.getConfigProvider(layer[ii], context[jj], tlistener[count]);
+ if (tmpAcp[ii] == null) {
+ printIt(" no ACP found in call to getConfigProvider() with layer=" + layer[ii] + "and context=" + context[jj]);
+ }
+ count++;
+ }
+ }
+
+ return tlistener;
+ }
+
+ /*
+ * This method creates and register a new ACP for each combination of the passed in layer and contexts. So if there are
+ * 3 layers and 3 contexts passed into this method, there will be 3 * 3 = 9 different ACPs registered in the passed in
+ * ACF. use the passed in "isPersistent" flag to specify if we want our registeration to be persistent or in-memory only
+ * type of registration.
+ */
+ public String[] createAndRegisterACPs(AuthConfigFactory acf, boolean isPersistent, String[] layer, String[] context) throws Exception {
+
+ TSAuthConfigProviderStandalone acp;
+ String[] regIds = new String[layer.length * context.length];
+
+ try {
+ // register new acp's
+ int count = 0;
+ for (int ii = 0; ii < layer.length; ii++) {
+ for (int jj = 0; jj < context.length; jj++) {
+ String desc = AuthConfigProviderDesc + " layer=" + ii + " " + " ctxt=" + jj;
+ if (isPersistent) {
+ // do persistent registration
+ regIds[count] = acf.registerConfigProvider(AuthConfigProviderClass, null, layer[ii], context[jj], desc);
+ } else {
+ // do in-memory registration
+ acp = new TSAuthConfigProviderStandalone((Map) null, null);
+ regIds[count] = acf.registerConfigProvider(acp, layer[ii], context[jj], desc);
+ }
+
+ // JASPIC:SPEC:336
+ boolean bb = verifyRegContextPersitentVal(acf, regIds[count], isPersistent);
+ if (!bb) {
+ // failure - our reg context did not have setting that matches the
+ // type of registration we used
+ String ss = new String("ERROR - RegistrationContext.isPersistent() mismatch");
+ printIt(ss);
+ throw new Exception(ss);
+ }
+
+ String str = "regId=" + regIds[count] + " for layer=" + ii + " " + " ctxt=" + jj;
+ printIt(str);
+ count++;
+ }
+ }
+
+ } catch (Exception ex) {
+ printIt("Got Exception in createAndRegisterACPs()");
+ throw ex;
+ }
+
+ return regIds;
+ }
+
+ public void printIt(String str) {
+ if (out == null) {
+ System.out.println(str);
+ } else {
+ // lets print them both so we get info in server.log and client side log
+ out.println(str);
+ System.out.println(str);
+ }
+ }
+
+ // --------------------------------------------------------------------
+ // Nested Class: MyRegistrationListener
+ //
+ public class MyRegistrationListener implements RegistrationListener {
+ String theProfileLayer = null;
+
+ String appContext = null;
+
+ boolean notified = false;
+
+ public MyRegistrationListener() {
+ }
+
+ public MyRegistrationListener(String theProfileLayer, String appContext) {
+ this.theProfileLayer = theProfileLayer;
+ this.appContext = appContext;
+ }
+
+ public String getProfileLayer() {
+ return this.theProfileLayer;
+ }
+
+ public void setProfileLayer(String val) {
+ this.theProfileLayer = val;
+ }
+
+ public String getAppContext() {
+ return this.appContext;
+ }
+
+ public void setAppContext(String val) {
+ this.appContext = val;
+ }
+
+ public void resetNotifyFlag() {
+ notified = false;
+ }
+
+ public boolean notified() {
+ return notified;
+ }
+
+ public boolean check(String layer, String context) {
+ return true;
+ }
+
+ @Override
+ public void notify(String layer, String context) {
+ boolean bLayersMatch = (theProfileLayer == layer) || theProfileLayer.equals(layer);
+ boolean bContextsMatch = (appContext == context) || appContext.equals(context);
+
+ if (bLayersMatch && bContextsMatch) {
+ // successful notification
+ } else {
+ // error - notify had problem
+ }
+ }
+ } // end Nested Class MyRegistrationListener
+
+} // end Outer Class CommonTests
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/CommonUtils.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/CommonUtils.java
new file mode 100644
index 0000000..cc3e8cf
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/CommonUtils.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationEntry;
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationXMLFileProcessor;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.AuthConfigProvider;
+import jakarta.security.auth.message.config.RegistrationListener;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ *
+ * @author Oracle
+ */
+public class CommonUtils implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ public CommonUtils() {
+
+ }
+
+ public static AuthConfigFactory register(String logFileLocation, String providerConfigurationFileLocation, String vendorAuthConfigFactoryClass) {
+
+ AuthConfigFactory acf = null;
+ try {
+
+ printVerticalIndent();
+
+ // Get an instance of Vendor's AuthConfigFactory
+ AuthConfigFactory vFactory = getAuthConfigFactory(vendorAuthConfigFactoryClass);
+
+ // Set vendor's AuthConfigFactory
+ AuthConfigFactory.setFactory(vFactory);
+
+ // Get system default AuthConfigFactory
+ acf = AuthConfigFactory.getFactory();
+
+ if (acf != null) {
+ printIt("Default AuthConfigFactory class name = " + acf.getClass().getName());
+ } else {
+ printError("Default AuthConfigFactory is null" + " can't register TestSuite Providers with null");
+ return null;
+ }
+
+ /**
+ * Read the ProviderConfiguration XML file This file contains the list of providers that needs to be loaded by the
+ * vendor's default AuthConfigFactory
+ */
+ Collection providerConfigurationEntriesCollection = readProviderConfigurationXMLFile(
+ providerConfigurationFileLocation);
+
+ ProviderConfigurationEntry pce = null;
+
+ printVerticalIndent();
+ Iterator iterator = providerConfigurationEntriesCollection.iterator();
+ while (iterator.hasNext()) {
+ // obtain each ProviderConfigurationEntry and register it
+ // with vendor's default AuthConfigFactory
+ pce = iterator.next();
+
+ if (pce != null) {
+ printIt("pce.getProviderClassName() = " + pce.getProviderClassName());
+ printIt("pce.getMessageLayer() = " + pce.getMessageLayer());
+ printIt("pce.getApplicationContextId() = " + pce.getApplicationContextId());
+ printIt("pce.getRegistrationDescription() = " + pce.getRegistrationDescription());
+ if (pce.getProperties() != null) {
+ printIt("pce.getProperties.toString() = " + pce.getProperties().toString());
+ } else {
+ printIt("pce.getProperties() = null");
+ }
+
+ printIt("Registering Provider " + pce.getProviderClassName() + " ...");
+ Map newProps = getCleanACPProps(pce.getProperties());
+ acf.registerConfigProvider(pce.getProviderClassName(), newProps, pce.getMessageLayer(), pce.getApplicationContextId(),
+ pce.getRegistrationDescription());
+ printIt("Registration Successful");
+ } else {
+ printIt("WARNING: pce was null and probably should not have been.");
+ }
+ }
+ printVerticalIndent();
+
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory";
+ msg = msg + "or ACF.setFactory(). Check your server side security policies.";
+ printIt(msg);
+ ex.printStackTrace();
+
+ } catch (Exception e) {
+ printIt("Error Registering TestSuite AuthConfig Providers");
+ e.printStackTrace();
+ }
+
+ return acf;
+ }
+
+ private static Map getCleanACPProps(Map origProps) {
+ if (origProps == null) {
+ return null;
+ }
+
+ HashMap props = new HashMap<>();
+
+ // loop thru passed in props and remove anything that is
+ // not of type String since only Strings are allowed in our
+ // calls to registerConfigProvider()
+ for (String key : origProps.keySet()) {
+ if (key != null) {
+ Object val = origProps.get(key);
+ if ((val != null) && ((val instanceof java.lang.String))) {
+ // we found entry that is not String so remove it
+ props.put(key, (String) val);
+ printIt("added key=" + key + " with value = " + val);
+ } else {
+ printIt("found non-string value for key=" + key);
+ }
+ }
+ }
+
+ return props;
+ }
+
+ /**
+ * This method instantiates and ruturns a AuthConfigFactory based on the specified className
+ */
+ public static AuthConfigFactory getAuthConfigFactory(String className) {
+ AuthConfigFactory vFactory = null;
+
+ if (className != null) {
+ try {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Class clazz = Class.forName(className, true, loader);
+ vFactory = (AuthConfigFactory) clazz.newInstance();
+ printIt("Instantiated Vendor's AuthConfigFactory");
+ } catch (Exception e) {
+ printIt("Error instantiating vendor's " + "AuthConfigFactory class :" + className);
+ e.printStackTrace();
+ }
+ }
+
+ return vFactory;
+ }
+
+ /**
+ * This method resets the default ACF.
+ *
+ */
+ public static void resetDefaultACF() throws Exception {
+ try {
+ printIt("resetting ACF back to CTS default: " + JASPICData.TSSV_ACF);
+ AuthConfigFactory origAcf = getAuthConfigFactory(JASPICData.TSSV_ACF);
+ AuthConfigFactory.setFactory(origAcf);
+ } catch (Exception ex) {
+ printIt("Exception while trying to restore original factory class in ACFSwitchFactorys");
+ throw ex;
+ }
+ }
+
+ /*
+ * Read the provider configuration XML file and registers each provider with Vendor's default AuthConfigFactory
+ */
+ public static Collection readProviderConfigurationXMLFile(String acpCfgFile) {
+ Collection providerConfigurationEntriesCollection = null;
+
+ printIt("Reading TestSuite Providers from :" + acpCfgFile);
+ try {
+ // Given the provider configuration xml file
+ // This reader parses the xml file and stores the configuration
+ // entries as a collection.
+ ProviderConfigurationXMLFileProcessor configFileProcessor = new ProviderConfigurationXMLFileProcessor(acpCfgFile);
+
+ // Retrieve the ProviderConfigurationEntries collection
+ providerConfigurationEntriesCollection = configFileProcessor.getProviderConfigurationEntriesCollection();
+
+ printIt("TestSuite Providers read successfully " + "from ProviderConfiguration.xml file");
+
+ return providerConfigurationEntriesCollection;
+
+ } catch (Exception e) {
+ printIt("Error loading Providers");
+ e.printStackTrace();
+ }
+ return null;
+
+ }
+
+ public static void printVerticalIndent() {
+ printIt("**********************************************************");
+ printIt("\n");
+ }
+
+ public static void dumpProviders(AuthConfigFactory acf, String[] regIDs) {
+
+ printIt("****************************************************************");
+ printIt("******* Dumping AuthConfigFactory registered providers *******");
+ for (int ii = 0; ii < regIDs.length; ii++) {
+ if (regIDs[ii] != null) {
+ printIt("registrationID[" + ii + "] = " + regIDs[ii]);
+ AuthConfigFactory.RegistrationContext rc = acf.getRegistrationContext(regIDs[ii]);
+ printIt("AppContext = " + rc.getAppContext());
+ printIt("Message layer = " + rc.getMessageLayer());
+ printIt("Description = " + rc.getDescription());
+ printIt("isPersistent = " + rc.isPersistent());
+ }
+ }
+ printIt("****************************************************************");
+ printIt(" ");
+ }
+
+ public static String getRegisteredProviderID(String msgLayer, String appContext, RegistrationListener rl) {
+ String regID = null;
+
+ AuthConfigFactory acf = AuthConfigFactory.getFactory();
+ AuthConfigProvider acp = acf.getConfigProvider(msgLayer, appContext, rl);
+
+ String[] allIDs = acf.getRegistrationIDs(acp);
+ for (int ii = 0; ii < allIDs.length; ii++) {
+ AuthConfigFactory.RegistrationContext rc = acf.getRegistrationContext(allIDs[ii]);
+ if (rc != null) {
+ String mlayer = rc.getMessageLayer();
+ String appctxt = rc.getAppContext();
+ if (msgLayer.equals(mlayer) && appContext.equals(appctxt)) {
+ regID = allIDs[ii];
+ break;
+ }
+ } else {
+ printIt("no registrationContext for regID = " + allIDs[ii]);
+ }
+ }
+
+ return regID;
+ }
+
+ public static void printIt(String str) {
+ System.out.println(str);
+ }
+
+ public static void printError(String str) {
+ System.err.println(str);
+ }
+
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/IdUtil.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/IdUtil.java
new file mode 100644
index 0000000..0d670db
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/IdUtil.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationEntry;
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationXMLFileProcessor;
+import ee.jakarta.tck.authentication.test.basic.sam.TSFileHandler;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import ee.jakarta.tck.authentication.test.common.logging.server.TSXMLFormatter;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.logging.Level;
+
+/**
+ *
+ * @author Raja Perumal
+ */
+public class IdUtil {
+
+ private static ProviderConfigurationXMLFileProcessor configFileProcessor = null;
+
+ private static TSLogger logger = null;
+
+ public IdUtil() {
+ initializeTSLogger();
+ }
+
+ /*
+ * 1) Reads the provider configuration XML file, 2) Examines providers 3) If possible return a non-null
+ * ApplicationContextId for a given layer 4) If no suitable ApplicationContextId found it returns an empty string
+ */
+ public static String getAppContextId(String msgLayer) {
+ String providerConfigFileLocation = System.getProperty("provider.configuration.file");
+
+ try {
+ // Given the provider configuration xml file
+ // This reader parses the xml file and stores the configuration
+ // entries as a collection.
+ configFileProcessor = new ProviderConfigurationXMLFileProcessor(providerConfigFileLocation);
+
+ // Retrieve the ProviderConfigurationEntries collection
+ Collection providerConfigurationEntriesCollection = configFileProcessor
+ .getProviderConfigurationEntriesCollection();
+
+ ProviderConfigurationEntry pce = null;
+ String appContextId = null;
+
+ Iterator iterator = providerConfigurationEntriesCollection.iterator();
+ while (iterator.hasNext()) {
+ // obtain each ProviderConfigurationEntry and register it
+ // with TSAuthConfigFactory
+ pce = iterator.next();
+
+ if (pce != null) {
+ appContextId = pce.getApplicationContextId();
+ String pceMsgLayer = pce.getMessageLayer();
+
+ if (msgLayer.equalsIgnoreCase(pceMsgLayer) && !appContextId.equalsIgnoreCase("null")) {
+ return appContextId;
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ if ((e.getMessage() != null) && (!e.getMessage().equals(""))) {
+ logger.log(Level.SEVERE, e.getMessage());
+ } else {
+ logger.log(Level.SEVERE, "Error in getAppContextId()");
+ }
+ }
+
+ // if here, we must have had an app contextId that was null or
+ // unidentifyable msgLayer
+ return "";
+ }
+
+ private static void initializeTSLogger() {
+ String logFileLocation = null;
+ if (logger != null) {
+ return;
+ } else {
+ try {
+ logFileLocation = System.getProperty("log.file.location");
+ System.out.println("logFileLocation = " + logFileLocation);
+ if (logFileLocation != null) {
+ logger = TSLogger.getTSLogger(JASPICData.LOGGER_NAME);
+ boolean appendMode = true;
+
+ // create a new file
+ TSFileHandler fileHandler = new TSFileHandler(logFileLocation + "/" + JASPICData.DEFAULT_LOG_FILE, appendMode);
+ fileHandler.setFormatter(new TSXMLFormatter());
+ logger.addHandler(fileHandler);
+ } else {
+ throw new RuntimeException("log.file.location not set");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("TSLogger Initialization failed", e);
+ }
+ }
+ }
+}
diff --git a/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/JASPICData.java b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/JASPICData.java
new file mode 100644
index 0000000..05be33e
--- /dev/null
+++ b/tck/spi/common/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/JASPICData.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2007, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigFactory;
+
+/**
+ *
+ * @author Sun Microsystems
+ */
+public class JASPICData {
+
+ // these are the Jakarta Authentication supported profile message-layers
+ public final static String LAYER_SERVLET = "HttpServlet";
+
+ public final static String LAYER_SOAP = "SOAP";
+
+ // this is a name that we will use to internally reference our logger
+ public final static String LOGGER_NAME = "jsr196";
+
+ // This log file is used on the appserver side by our cts tests
+ // to verify success/failures of our tests that involve a need to
+ // know that status of an exchange between a client and server.
+ public final static String DEFAULT_LOG_FILE = "authentication-trace-log.xml";
+
+ public final static String MOD_CLASS_NAME = "moduleClassKey";
+
+ public final static String SVC_SUBJECT_KEY = "com.sun.ts.tests.jaspic.serviceSubjectKey";
+
+ // define some statics for the cts AuthConfigFactory implementation and
+ // the RI's implementation of the AuthConfigFactory
+ public final static String TSSV_ACF = TSAuthConfigFactory.class.getName();
+
+ // definitions for Servlet Container Profile (SCP)
+ public final static String SCP_CONTEXT_PATH = "spitests_servlet_web";
+
+ public final static String AUTHSTAT_FAILURE_ND = "ModuleAuthStatusFailureNoDispatch";
+
+ public final static String AUTHSTAT_SENDFAILURE_ND = "ModuleAuthStatusSendFailureNoDispatch";
+
+ public final static String AUTHSTAT_SENDCONT_ND = "ModuleAuthStatusSendContinueNoDispatch";
+
+ public final static String AUTHSTAT_SENDSUCCESS_ND = "ModuleAuthStatusSendSuccessNoDispatch";
+
+ public final static String AUTHSTAT_SUCCESS_ND = "ModuleAuthStatusSuccessNoDispatch";
+
+ public final static String AUTHSTAT_THROW_EX_ND = "ModuleAuthStatusThrowExNoDispatch";
+
+ public final static String AUTHSTAT_OPT_SUCCESS = "AuthStatusOptionalSuccess";
+
+ public final static String AUTHSTAT_MAND_SUCCESS = "AuthStatusMandatorySuccess";
+
+ public final static String AUTHSTAT_FAILURE_D = "ModuleAuthStatusFailureDispatch";
+
+ public final static String AUTHSTAT_SENDFAILURE_D = "ModuleAuthStatusSendFailureDispatch";
+
+ public final static String AUTHSTAT_SENDCONT_D = "ModuleAuthStatusSendContinueDispatch";
+
+ public final static String AUTHSTAT_SENDSUCCESS_D = "ModuleAuthStatusSendSuccessDispatch";
+
+ public final static String AUTHSTAT_SUCCESS_D = "ModuleAuthStatusSuccessDispatch";
+
+ public final static String AUTHSTAT_THROW_EX_D = "ModuleAuthStatusThrowExDispatch";
+
+}
diff --git a/tck/spi/common/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer b/tck/spi/common/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer
new file mode 100644
index 0000000..7a4388c
--- /dev/null
+++ b/tck/spi/common/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer
@@ -0,0 +1 @@
+ee.jakarta.tck.authentication.test.basic.servlet.AuthFactoryContainerInitializer
\ No newline at end of file
diff --git a/tck/spi/common/src/main/webapp/WEB-INF/web.xml b/tck/spi/common/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..180833e
--- /dev/null
+++ b/tck/spi/common/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ spi_servlet
+
+
+ BASIC
+ default
+
+
+
diff --git a/tck/spi/pom.xml b/tck/spi/pom.xml
new file mode 100644
index 0000000..09c1019
--- /dev/null
+++ b/tck/spi/pom.xml
@@ -0,0 +1,41 @@
+
+
+
+
+ 4.0.0
+
+
+ org.eclipse.ee4j.tck.authentication
+ jakarta-authentication-tck
+ 3.1.0-SNAPSHOT
+
+
+ spi
+ pom
+
+ Jakarta Authentication TCK - spi
+
+
+ common
+
+ servlet
+
+ soap
+
+
+
diff --git a/tck/spi/servlet/auth.conf b/tck/spi/servlet/auth.conf
new file mode 100644
index 0000000..6733343
--- /dev/null
+++ b/tck/spi/servlet/auth.conf
@@ -0,0 +1,34 @@
+reg-entry {
+ con-entry {
+ ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigProvider
+ AuthStatus_SEND_SUCCESS:false
+ requestPolicy:USER_NAME_PASSWORD
+ }
+ reg-ctx {
+ layer:SOAP
+ app-ctx:null
+ description:TestSuite JSR 196 Config Provider
+ }
+ reg-ctx {
+ layer:SOAP
+ app-ctx:localhost /Hello_web/Hello
+ description:TestSuite JSR 196 Config Provider
+ }
+}
+reg-entry {
+ con-entry {
+ ee.jakarta.tck.authentication.test.basic.sam.TSAuthConfigProviderServlet
+ AuthStatus_SEND_SUCCESS:true
+ requestPolicy:USER_NAME_PASSWORD
+ }
+ reg-ctx {
+ layer:HttpServlet
+ app-ctx:server /spitests_servlet_web
+ description:Registration for TSAuthConfigProviderServlet using spitests_servlet_web
+ }
+ reg-ctx {
+ layer:HttpServlet
+ app-ctx:server /spitests_servlet_web/WrapperServlet
+ description:Registration for TSAuthConfigProviderServlet using spitests_servlet_web
+ }
+}
diff --git a/tck/spi/servlet/pom.xml b/tck/spi/servlet/pom.xml
new file mode 100644
index 0000000..75956d2
--- /dev/null
+++ b/tck/spi/servlet/pom.xml
@@ -0,0 +1,51 @@
+
+
+
+ 4.0.0
+
+
+ org.eclipse.ee4j.tck.authentication
+ spi
+ 3.1.0-SNAPSHOT
+
+
+ spi.servlet
+ war
+
+ Jakarta Authentication TCK - Profile SPI Servlet
+
+ A lot of tests about the nitty gritty regarding the SPI per profile.
+
+
+
+
+ org.jakartaee
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+ org.eclipse.ee4j.tck.authentication
+ spi.common
+ ${project.version}
+
+
+
+
+ spitests_servlet_web
+
+
diff --git a/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ACFTestServlet.java b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ACFTestServlet.java
new file mode 100644
index 0000000..ca37b21
--- /dev/null
+++ b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ACFTestServlet.java
@@ -0,0 +1,629 @@
+/*
+ * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.LAYER_SERVLET;
+
+import ee.jakarta.tck.authentication.test.basic.sam.TSAuthConfigProviderServlet;
+import jakarta.annotation.security.DeclareRoles;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.AuthConfigProvider;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.HttpConstraint;
+import jakarta.servlet.annotation.HttpMethodConstraint;
+import jakarta.servlet.annotation.ServletSecurity;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+@DeclareRoles({ "Administrator", "Manager", "Employee" })
+@ServletSecurity(value = @HttpConstraint(rolesAllowed = { "Administrator" }), httpMethodConstraints = {
+ @HttpMethodConstraint(value = "GET", rolesAllowed = "Administrator"),
+ @HttpMethodConstraint(value = "POST", rolesAllowed = "Administrator") })
+@WebServlet(name = "ACFTestServlet", urlPatterns = { "/ACFTestServlet" })
+public class ACFTestServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ private String logFileLocation;
+ private String servletAppContext;
+ private String providerConfigFileLocation;
+ private String vendorACFClass;
+ private String testMethod;
+
+ private transient CommonTests commonTests;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ doPost(request, response);
+ }
+
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ doTests(request, response);
+ }
+
+ public void doTests(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ } catch (Exception ex) {
+ debug("got exception in ACFTestServlet");
+ ex.printStackTrace();
+ }
+ commonTests = new CommonTests(out);
+
+ // get some common props
+ getPropsAndParams(request, response);
+
+ if (testMethod == null) {
+ getRegistrationContextId(request, response);
+ AuthConfigFactoryVerifyPersistence(request, response);
+
+ } else if (testMethod.equals("ACFRemoveRegistration")) {
+ ACFRemoveRegistration(request, response);
+
+ } else if (testMethod.equals("ACFGetRegistrationIDs")) {
+ ACFGetRegistrationIDs(request, response);
+
+ } else if (testMethod.equals("ACFGetRegistrationContext")) {
+ ACFGetRegistrationContext(request, response);
+
+ } else if (testMethod.equals("ACFDetachListener")) {
+ ACFDetachListener(request, response);
+
+ } else if (testMethod.equals("ACFGetFactory")) {
+ ACFGetFactory(request, response);
+
+ } else if (testMethod.equals("ACFSwitchFactorys")) {
+ ACFSwitchFactorys(request, response);
+
+ } else if (testMethod.equals("testACFComesFromSecFile")) {
+ testACFComesFromSecFile(request, response);
+
+ } else if (testMethod.equals("ACFPersistentRegisterOnlyOneACP")) {
+ ACFPersistentRegisterOnlyOneACP(request, response);
+
+ } else if (testMethod.equals("ACFInMemoryRegisterOnlyOneACP")) {
+ ACFInMemoryRegisterOnlyOneACP(request, response);
+
+ } else if (testMethod.equals("ACFUnregisterACP")) {
+ ACFUnregisterACP(request, response);
+
+ } else if (testMethod.equals("AuthConfigFactoryRegistration")) {
+ AuthConfigFactoryRegistration(request, response);
+
+ } else if (testMethod.equals("ACFInMemoryNotifyOnUnReg")) {
+ ACFInMemoryNotifyOnUnReg(request, response);
+
+ } else if (testMethod.equals("ACFPersistentNotifyOnUnReg")) {
+ ACFPersistentNotifyOnUnReg(request, response);
+
+ } else if (testMethod.equals("ACFInMemoryPrecedenceRules")) {
+ ACFInMemoryPrecedenceRules(request, response);
+
+ } else if (testMethod.equals("ACFPersistentPrecedenceRules")) {
+ ACFPersistentPrecedenceRules(request, response);
+
+ } else if (testMethod.equals("ACFRemoveRegistrationWithBadId")) {
+ ACFRemoveRegistrationWithBadId(request, response);
+ }
+
+ // restore original (CTS) factory class
+ // note: this should be done in many of the calls but its a safety measure
+ // to ensure we are resetting things back to expected defaults
+ try {
+ CommonUtils.resetDefaultACF();
+ } catch (Exception ex) {
+ debug("ACFTestServlet: error calling CommonUtils.resetDefaultACF(): " + ex.getMessage());
+ ex.printStackTrace();
+ }
+ }
+
+ private void getPropsAndParams(HttpServletRequest request, HttpServletResponse response) {
+
+ // set logfile location
+ logFileLocation = System.getProperty("log.file.location");
+ if ((logFileLocation != null) && (-1 < logFileLocation.indexOf(JASPICData.DEFAULT_LOG_FILE))) {
+ // if here, we have logfile location value which contains
+ // JASPICData.DEFAULT_LOG_FILE
+ debug("logFileLocation already set");
+ } else {
+ debug("logFileLocation NOT set completely");
+ System.setProperty("log.file.location", logFileLocation);
+ }
+ debug("logFileLocation = " + logFileLocation);
+
+ // set provider config file
+ providerConfigFileLocation = System.getProperty("provider.configuration.file");
+ debug("TS Provider ConfigFile = " + providerConfigFileLocation);
+ if (providerConfigFileLocation == null) {
+ debug("ERROR: getPropsAndParams(): providerConfigFileLocation = null");
+ } else {
+ debug("getPropsAndParams(): providerConfigFileLocation = " + providerConfigFileLocation);
+ }
+
+ // set testMethod
+ testMethod = request.getParameter("method.under.test");
+
+ // set vendor class
+ vendorACFClass = System.getProperty("vendor.authconfig.factory");
+ if (vendorACFClass == null) {
+ debug("ERROR: getPropsAndParams(): vendorACFClass = null");
+ } else {
+ debug("getPropsAndParams(): vendorACFClass = " + vendorACFClass);
+ }
+
+ servletAppContext = IdUtil.getAppContextId(JASPICData.LAYER_SERVLET);
+
+ return;
+ }
+
+ /*
+ * This is testing that acf.removeRegistration(arg) will return FALSE when invalid arg supplied. (this requirement
+ * described in javadoc for api)
+ */
+ public void ACFRemoveRegistration(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ System.out.println("in ACFTestServlet.ACFRemoveRegistration");
+ commonTests._ACF_testFactoryRemoveRegistration();
+ System.out.println("in ACFTestServlet ... just called commonTests._ACF_testFactoryRemoveRegistration");
+
+ out = response.getWriter();
+ if (out != null) {
+ System.out.println("in ACFTestServlet ... out != null so passed");
+ out.println("ACFTestServlet->ACFRemoveRegistration() passed");
+ out.flush();
+ } else {
+ System.out.println("in ACFTestServlet ... out == null so failed");
+ }
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFRemoveRegistration() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /*
+ * This is testing that acf.getRegistrationIDs(acp) NEVER returns null hint: this must return empty array even if
+ * unrecognized acp. (this requirement described in javadoc for api)
+ */
+ public void ACFGetRegistrationIDs(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ commonTests._ACF_testFactoryGetRegistrationIDs();
+
+ out = response.getWriter();
+ if (out != null) {
+ out.println("ACFTestServlet->ACFGetRegistrationIDs() passed");
+ out.flush();
+ }
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFGetRegistrationIDs() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /*
+ * This is testing that acf.getRegistrationContext(string) returns NULL for an unrecognized string (this requirement
+ * described in javadoc for api)
+ */
+ public void ACFGetRegistrationContext(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ commonTests._ACF_testFactoryGetRegistrationContext();
+
+ out = response.getWriter();
+ if (out != null) {
+ out.println("ACFTestServlet->ACFGetRegistrationContext() passed");
+ out.flush();
+ }
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFGetRegistrationContext() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /*
+ * This is testing that acf.detachListener(...) returns non-NULL for an unfound listner (this requirement described in
+ * javadoc for api)
+ */
+ public void ACFDetachListener(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ commonTests._ACF_testFactoryDetachListener(vendorACFClass);
+
+ out = response.getWriter();
+ if (out != null) {
+ out.println("ACFTestServlet->ACFDetachListener() passed");
+ out.flush();
+ }
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFDetachListener() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ public void ACFGetFactory(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ commonTests._ACF_getFactory();
+
+ out = response.getWriter();
+ if (out != null) {
+ out.println("ACFTestServlet->ACFGetFactory() passed");
+ out.flush();
+ }
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACF_getFactory() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ public void ACFSwitchFactorys(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ commonTests._ACFSwitchFactorys(vendorACFClass);
+
+ if (out != null) {
+ out.println("ACFTestServlet->ACFSwitchFactorys() passed");
+ out.flush();
+ }
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFSwitchFactorys() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ public void testACFComesFromSecFile(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ commonTests._testACFComesFromSecFile();
+ out.println("ACFTestServlet->testACFComesFromSecFile() passed");
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->testACFComesFromSecFile() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ public void ACFPersistentRegisterOnlyOneACP(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ commonTests._ACFRegisterOnlyOneACP(logFileLocation, providerConfigFileLocation, vendorACFClass, true);
+ out.println("ACFTestServlet->ACFPersistentRegisterOnlyOneACP() passed");
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFPersistentRegisterOnlyOneACP() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ public void ACFInMemoryRegisterOnlyOneACP(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ commonTests._ACFRegisterOnlyOneACP(logFileLocation, providerConfigFileLocation, vendorACFClass, false);
+ out.println("ACFTestServlet->ACFInMemoryRegisterOnlyOneACP() passed");
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFInMemoryRegisterOnlyOneACP() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ public void ACFUnregisterACP(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ commonTests._ACFUnregisterACP(logFileLocation, providerConfigFileLocation, vendorACFClass);
+ out.println("ACFTestServlet->ACFUnregisterACP() passed");
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFUnregisterACP() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /*
+ * This is verifying that the invocation of removeRegistration() with an invalid and non-existant regId will return
+ * false.
+ */
+ public void ACFRemoveRegistrationWithBadId(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ commonTests._ACFRemoveRegistrationWithBadId();
+ out.println("ACFTestServlet->ACFRemoveRegistrationWithBadId() passed");
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFRemoveRegistrationWithBadId() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Use the system properties to read the TestSuite providers defined in ProviderConfigruation.xml file and register
+ * them with vendor's authconfig factory.
+ */
+ public void AuthConfigFactoryRegistration(HttpServletRequest request, HttpServletResponse response) {
+
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ AuthConfigFactory registerACF = CommonUtils.register(logFileLocation, providerConfigFileLocation, vendorACFClass);
+
+ if (registerACF != null) {
+ out.println("ACFTestServlet->AuthConfigFactoryRegistration() passed");
+ } else {
+ out.println("ACFTestServlet->AuthConfigFactoryRegistration() failed");
+ }
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->AuthConfigFactoryRegistration() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ public void ACFInMemoryNotifyOnUnReg(HttpServletRequest request, HttpServletResponse response) {
+
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+
+ // test using in-memory registration
+ commonTests._ACFTestNotifyOnUnReg(vendorACFClass, false);
+
+ out.println("ACFTestServlet->ACFInMemoryNotifyOnUnReg() passed");
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFInMemoryNotifyOnUnReg() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ public void ACFPersistentNotifyOnUnReg(HttpServletRequest request, HttpServletResponse response) {
+
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+
+ // now test using persistent registration
+ commonTests._ACFTestNotifyOnUnReg(vendorACFClass, true);
+
+ out.println("ACFTestServlet->ACFPersistentNotifyOnUnReg() passed");
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFPersistentNotifyOnUnReg() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ public void ACFInMemoryPrecedenceRules(HttpServletRequest request, HttpServletResponse response) {
+
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+
+ // test using in-memory registration
+ commonTests._ACFTestPrecedenceRules(vendorACFClass, false);
+
+ out.println("ACFTestServlet->ACFInMemoryPrecedenceRules() passed");
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFInMemoryPrecedenceRules() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ public void ACFPersistentPrecedenceRules(HttpServletRequest request, HttpServletResponse response) {
+
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+
+ // now test using persistent registration
+ commonTests._ACFTestPrecedenceRules(vendorACFClass, true);
+
+ out.println("ACFTestServlet->ACFPersistentPrecedenceRules() passed");
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("ACFTestServlet->ACFPersistentPrecedenceRules() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Use the system properties to read the TestSuite providers defined in ProviderConfigruation.xml file and register
+ * them with vendor's authconfig factory.
+ *
+ *
+ * Description This will use an appContext value that was used to register a provider, and it will see if it can use the
+ * AuthConfigFactory.RegistrationContext API to try and access the same appContext value that was used during the
+ * registration process.
+ *
+ */
+ public void getRegistrationContextId(HttpServletRequest request, HttpServletResponse response) {
+ String appContext = "localhost /Hello_web/Hello";
+
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+
+ // register providers in vendor factory
+ AuthConfigFactory registeredACF = CommonUtils.register(logFileLocation, providerConfigFileLocation, vendorACFClass);
+ if (registeredACF == null) {
+ out.println("getRegistrationContextId failed");
+ }
+
+ // verify we can access a given provider (any provider) appcontext id
+ boolean bVerified = false;
+ AuthConfigFactory acf = AuthConfigFactory.getFactory();
+ String[] regIDs = acf.getRegistrationIDs(null);
+ for (int ii = 0; ii < regIDs.length; ii++) {
+ // loop through the ACF's registration ids
+
+ if (regIDs[ii] != null) {
+ AuthConfigFactory.RegistrationContext acfReg;
+ acfReg = acf.getRegistrationContext(regIDs[ii]);
+ if (acfReg != null) {
+ debug("appContext = " + appContext);
+ debug("acfReg.getAppContext() = " + acfReg.getAppContext());
+ debug("layer = " + acfReg.getMessageLayer());
+ String str = acfReg.getAppContext();
+ if ((str != null) && (str.equals(appContext))) {
+ // we found our provider info
+ debug("Found it : RegistrationID for our ACP=" + regIDs[ii]);
+ bVerified = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!bVerified) {
+ String msg = "Could not find appContext=" + appContext;
+ msg += " in the ACF's list of registration id info";
+ debug(msg);
+ out.println("getRegistrationContextId() TSProviders registration failed");
+ }
+
+ out.println("getRegistrationContextId() TSProviders registration passed");
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory() or ";
+ msg = msg + "ACF.setFactory(). You may need to explicitly set your server side security policies.";
+ if (out == null) {
+ System.out.println(msg);
+ } else {
+ out.println(msg);
+ }
+ ex.printStackTrace();
+ } catch (Exception ex) {
+ System.out.println("getRegistrationContextId() TSProviders registration failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Load vendor's AuthConfigFactory and make sure the registered providers return properly for the right message layer
+ * and appContextId
+ *
+ * Note: We test the persistance behaviour for vendor's AuthConfigFactory by registering providers from a persisted
+ * file, then we verify the registrations went correctly.
+ *
+ */
+ public void AuthConfigFactoryVerifyPersistence(HttpServletRequest request, HttpServletResponse response) {
+ boolean verified = false;
+
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+
+ // Register providers in vendor factory
+ AuthConfigFactory registerACF = CommonUtils.register(logFileLocation, providerConfigFileLocation, vendorACFClass);
+ if (registerACF != null) {
+ out.println("AuthConfigFactoryVerifyPersistence failed");
+ }
+
+ // Get system default AuthConfigFactory
+ AuthConfigFactory authConfigFactory = AuthConfigFactory.getFactory();
+
+ if (authConfigFactory != null) {
+ debug("Default ACF class name = " + authConfigFactory.getClass().getName());
+ verified = verifyRegistrations(authConfigFactory);
+ } else {
+ out.println("AuthConfigFactoryVerifyPersistence() failed");
+ debug("Default ACF is null" + " can't verify registrations for TestSuite Providers");
+ }
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory.";
+ msg = msg + " You may need to explicitly set your server side security policies.";
+ debug(msg);
+ ex.printStackTrace();
+
+ } catch (Exception e) {
+ System.out.println("AuthConfigFactoryVerifyPersistence() failed");
+ e.printStackTrace();
+ }
+
+ if (verified && out != null) {
+ out.println("AuthConfigFactoryVerifyPersistence() passed");
+ }
+ }
+
+ private boolean verifyRegistrations(AuthConfigFactory authConfigFactory) {
+ debug("Verifying Provider Registrations ...");
+
+ try {
+ // Get AuthConfigProviderServlet
+ AuthConfigProvider servletAuthConfigProvider = authConfigFactory.getConfigProvider(LAYER_SERVLET, servletAppContext, null);
+
+ if (servletAuthConfigProvider != null) {
+ if (servletAuthConfigProvider.getClass().getName().equals(TSAuthConfigProviderServlet.class.getName())) {
+ debug("TSAuthConfigProviderServlet registered for" + " message layer=HttpServlet" + " and appContextId="
+ + servletAppContext);
+ } else {
+ debug("Wrong provider registerd for " + " message layer=HttpServlet" + " and appContextId=" + servletAppContext);
+ return false;
+ }
+
+ } else {
+ debug("Error : No AuthConfigprovider registerd for" + " message layer=HttpServlet" + " and appContextId="
+ + servletAppContext);
+ return false;
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return true;
+ }
+
+ public void debug(String str) {
+ System.out.println(str);
+ }
+
+}
diff --git a/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AnotherMandatoryAuthen.java b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AnotherMandatoryAuthen.java
new file mode 100644
index 0000000..66aab40
--- /dev/null
+++ b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AnotherMandatoryAuthen.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import jakarta.annotation.security.DeclareRoles;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.HttpConstraint;
+import jakarta.servlet.annotation.HttpMethodConstraint;
+import jakarta.servlet.annotation.ServletSecurity;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+@DeclareRoles({ "Administrator", "Manager", "Employee" })
+@ServletSecurity(
+ value =
+ @HttpConstraint(rolesAllowed = { "Manager" }),
+ httpMethodConstraints = {
+ @HttpMethodConstraint(value = "GET", rolesAllowed = "Manager"),
+ @HttpMethodConstraint(value = "POST", rolesAllowed = "Manager") })
+@WebServlet(name = "AnotherMandatoryAuthen", urlPatterns = { "/AnotherMandatoryAuthen" })
+public class AnotherMandatoryAuthen extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ doPost(request, response);
+ printOut("Enterred AnotherMandatoryAuthen->doGet()", response);
+ }
+
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ System.out.println("In AnotherMandatoryAuthen->doPost()");
+
+ printOut("Enterred AnotherMandatoryAuthen->doPost()", response);
+ printOut("request.getServletPath() = " + request.getServletPath(), response);
+ printOut("request.getPathInfo() = " + request.getPathInfo(), response);
+ printOut("request.getMethod() = " + request.getMethod(), response);
+ }
+
+ @Override
+ public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ System.out.println("In AnotherMandatoryAuthen->service()");
+ printOut("Enterred AnotherMandatoryAuthen->service()", response);
+ }
+
+ private void printOut(String str, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ out = null;
+ }
+
+ if (out != null) {
+ out.println(str);
+ } else {
+ System.out.println(str);
+ }
+ }
+
+}
diff --git a/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AuthFactoryContainerInitializer.java b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AuthFactoryContainerInitializer.java
new file mode 100644
index 0000000..2fc4315
--- /dev/null
+++ b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AuthFactoryContainerInitializer.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigFactory;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.servlet.ServletContainerInitializer;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import java.util.Set;
+
+public class AuthFactoryContainerInitializer implements ServletContainerInitializer {
+
+ @Override
+ public void onStartup(Set> c, ServletContext ctx) throws ServletException {
+ AuthConfigFactory.setFactory(new TSAuthConfigFactory());
+ }
+
+}
diff --git a/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AuthStatusMandatorySuccess.java b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AuthStatusMandatorySuccess.java
new file mode 100644
index 0000000..99f5868
--- /dev/null
+++ b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/AuthStatusMandatorySuccess.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import jakarta.annotation.security.DeclareRoles;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.HttpConstraint;
+import jakarta.servlet.annotation.HttpMethodConstraint;
+import jakarta.servlet.annotation.ServletSecurity;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+@DeclareRoles({ "Administrator", "Manager", "Employee" })
+@ServletSecurity(
+ value =
+ @HttpConstraint(rolesAllowed = { "Administrator" }),
+ httpMethodConstraints = {
+ @HttpMethodConstraint(value = "GET", rolesAllowed = "Administrator"),
+ @HttpMethodConstraint(value = "POST", rolesAllowed = "Administrator") })
+@WebServlet(name = "AuthStatusMandatorySuccess", urlPatterns = { "/AuthStatusMandatorySuccess" })
+public class AuthStatusMandatorySuccess extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ PrintWriter out = response.getWriter();
+ doPost(request, response);
+ out.println("Enterred AuthStatusMandatorySuccess->doGet()");
+ }
+
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ System.out.println("In AuthStatusMandatorySuccess->doPost()");
+ doTests(request, response);
+ }
+
+ public void doTests(HttpServletRequest request, HttpServletResponse response) {
+ System.out.println("In AuthStatusMandatorySuccess->doTests()");
+
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+
+ // get some common props
+ String testMethod = request.getParameter("method.under.test");
+
+ if (testMethod == null) {
+
+ out.println("request.getServletPath() = " + request.getServletPath());
+ out.println("request.getPathInfo() = " + request.getPathInfo());
+ out.println("request.getMethod() = " + request.getMethod());
+
+ } else if (testMethod.equals("testSecRespCalledAfterSvcInvoc")) {
+ _testSecRespCalledAfterSvcInvoc(request, response);
+ }
+ } catch (Exception ex) {
+ System.out.println("WrapperServlet->testRequestWrapper() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /*
+ * This should be satisfying assertion JASPIC:SPEC:108.
+ */
+ public void _testSecRespCalledAfterSvcInvoc(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ PrintWriter out = response.getWriter();
+
+ out.println("Enterred AuthStatusMandatorySuccess->_testSecRespCalledAfterSvcInvoc()");
+ System.out.println("In AuthStatusMandatorySuccess->_testSecRespCalledAfterSvcInvoc()");
+
+ // see if a cts proprietary requestAttribute was set in the secureResponse
+ // call and if so, we have a problem. The secure response should be called
+ // AFTER this servlet invocation thus we should not see this attribute set
+ // yet. If set, it means our secureResponse was called BEFOR the service
+ // invocation and thats violation of jaspic 1.1. spec (section 3.8.3.2)
+ // also
+ // see https://java.net/jira/browse/JASPIC_SPEC-9
+ String wasSecureResponseInvokedYet = (String) request.getAttribute("secureRespCalled");
+ if ((wasSecureResponseInvokedYet != null) && (wasSecureResponseInvokedYet.equalsIgnoreCase("true"))) {
+ // error - the "secureRespCalled" attribute was set and that should
+ // only occur in secureResponse which indicates a problem since the
+ // secureResponse should not get called before service invocation.
+ System.out.println("ERROR - secureResponse called before service invocation");
+ out.println("testSecRespCalledAfterSvcInvoc() failed");
+ return;
+ } else if (wasSecureResponseInvokedYet == null) {
+ // This is good and validates assertion: JASPIC:SPEC:108
+ // The attribue was NOT set in secureResponse, so it must not
+ // have been called before the service invocation of this servlet
+ System.out.println(
+ "_testSecRespCalledAfterSvcInvoc() secureResponse NOT called before service invocation - which is correct!");
+ out.println("testSecRespCalledAfterSvcInvoc() passed");
+ }
+
+ String wasValidateRequestInvokedYet = (String) request.getAttribute("validateReqCalled");
+ if ((wasValidateRequestInvokedYet == null) || (!wasValidateRequestInvokedYet.equalsIgnoreCase("true"))) {
+ // ERROR - the only reason we should be here is if there was a Multi-msg
+ // dialog
+ // (per spec 3.8.3) but that should NOT be the case thus we should NOT
+ // get in here as caller identity should've been established in
+ // validateRequest already.
+ System.out.println("ERROR - validateRequest NOT called before service invocation");
+ out.println("testSecRespCalledAfterSvcInvoc() failed");
+ return;
+ } else {
+ // good - caller identity was established in validateRequest already,
+ // which
+ // is why we correctly see "validateReqCalled" request attribute was
+ // set.
+ System.out.println("_testSecRespCalledAfterSvcInvoc() validateRequest was correctly called BEFORE service invocation");
+ out.println("testSecRespCalledAfterSvcInvoc() passed");
+ }
+
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("AuthStatusMandatorySuccess->_testSecRespCalledAfterSvcInvoc() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ }
+
+ public void debug(String str) {
+ System.out.println(str);
+ }
+
+}
diff --git a/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ModTestServlet.java b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ModTestServlet.java
new file mode 100644
index 0000000..2977ff9
--- /dev/null
+++ b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/ModTestServlet.java
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import jakarta.annotation.security.DeclareRoles;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.HttpConstraint;
+import jakarta.servlet.annotation.HttpMethodConstraint;
+import jakarta.servlet.annotation.ServletSecurity;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.security.Principal;
+
+@DeclareRoles({ "Administrator", "Manager", "Employee" })
+@ServletSecurity(
+ value =
+ @HttpConstraint(rolesAllowed = { "Administrator" }),
+ httpMethodConstraints = {
+ @HttpMethodConstraint(value = "GET", rolesAllowed = "Administrator"),
+ @HttpMethodConstraint(value = "POST", rolesAllowed = "Administrator") })
+@WebServlet(name = "ModTestServlet", urlPatterns = { "/ModTestServlet" })
+public class ModTestServlet extends HttpServlet {
+
+ private String logFileLocation;
+ private String servletAppContext = null;
+ private String providerConfigFileLocation;
+ private String testMethod = null;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->doGet()");
+
+ doTests(request, response);
+
+ out.println("Laving ModTestServlet->doGet()");
+ }
+
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ System.out.println("In ModTestServlet->doPost()");
+
+ doTests(request, response);
+
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->doPost()");
+ }
+
+ @Override
+ public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ System.out.println("In ModTestServlet->service()");
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->service()");
+
+ super.service(request, response);
+ }
+
+ public void doTests(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ } catch (Exception ex) {
+ debug("got exception in ModTestServlet");
+ ex.printStackTrace();
+ }
+
+ // get some common props that are passed into our servlet request
+ getPropsAndParams(request, response);
+
+ if (testMethod.equals("testAuthenResultsOnHttpServlet")) {
+ MTSAuthenResultsOnHttpServlet(request, response);
+ } else if (testMethod.equals("testAuthenIsUserInRole")) {
+ MTSAuthenIsUserInRole(request, response);
+ } else if (testMethod.equals("testRemoteUserCorrespondsToPrin")) {
+ MTSRemoteUserCorrespondsToPrin(request, response);
+ } else if (testMethod.equals("testAuthenAfterLogout")) {
+ testAuthenAfterLogout(request, response);
+ } else if (testMethod.equals("testGPCIsUserInRole")) {
+ testGPCIsUserInRole(request, response);
+ } else if (testMethod.equals("testGPCGetUserPrincipal")) {
+ testGPCGetUserPrincipal(request, response);
+ } else if (testMethod.equals("testGPCGetRemoteUser")) {
+ testGPCGetRemoteUser(request, response);
+ } else if (testMethod.equals("testGPCGetAuthType")) {
+ testGPCGetAuthType(request, response);
+ } else {
+ // if here, it most likely means that we ran a test from within
+ // Client.java which
+ // invoked this servlet with the only intent being to check if access
+ // could be
+ // made. Some tests only care that they can access this servlet and do NOT
+ // need to run any particular testMethod in here.
+ debug("WARNING: ModTestServlet,doTests() testMethod not recognized: " + testMethod);
+ }
+ }
+
+ // this pulls out some params that are passed in on our servlet req
+ // that is made from within the client code (e.g. Client.java).
+ private void getPropsAndParams(HttpServletRequest req, HttpServletResponse response) {
+
+ // set logfile location
+ logFileLocation = req.getParameter("log.file.location");
+ if ((logFileLocation != null) && (-1 < logFileLocation.indexOf(JASPICData.DEFAULT_LOG_FILE))) {
+ // if here, we have logfile location value which contains
+ // JASPICData.DEFAULT_LOG_FILE
+ debug("logFileLocation already set");
+ } else if (logFileLocation != null) {
+ debug("logFileLocation NOT set completely");
+ System.setProperty("log.file.location", logFileLocation);
+ } else {
+ debug("ModTestServlet: logFileLocation null");
+ }
+ debug("logFileLocation = " + logFileLocation);
+
+ // set provider config file
+ providerConfigFileLocation = req.getParameter("provider.configuration.file");
+ debug("TS Provider ConfigFile = " + providerConfigFileLocation);
+ if (providerConfigFileLocation == null) {
+ debug("ERROR: getPropsAndParams(): providerConfigFileLocation = null");
+ } else {
+ debug("getPropsAndParams(): providerConfigFileLocation = " + providerConfigFileLocation);
+ }
+
+ // set testMethod
+ testMethod = req.getParameter("method.under.test");
+
+ servletAppContext = IdUtil.getAppContextId(JASPICData.LAYER_SERVLET);
+
+ return;
+ }
+
+ /*
+ * This should be satisfying assertion JASPIC:SPEC:322.
+ */
+ public void MTSAuthenResultsOnHttpServlet(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->MTSAuthenResultsOnHttpServlet()");
+ System.out.println("In ModTestServlet->MTSAuthenResultsOnHttpServlet()");
+
+ // after successful login, we should see non-null values for all of these!
+ String strAuthType = request.getAuthType();
+ String strRemoteUser = request.getRemoteUser();
+ Principal pp = request.getUserPrincipal();
+
+ if ((strAuthType != null) && (strRemoteUser != null) && (pp != null)) {
+ out.println("request.getAuthType() = " + strAuthType);
+ out.println("request.getRemoteUser() = " + strRemoteUser);
+ out.println("request.getUserPrincipal() = " + pp.toString());
+ out.println("Authentication results on HttpServletRequest ok.");
+ out.println("ModTestServlet->testAuthenResultsOnHttpServlet() passed");
+ } else if ((strRemoteUser == null) && (pp == null) && (strAuthType == null)) {
+ out.println("request.getRemoteUser() == pp == null");
+ out.println("ModTestServlet->testAuthenResultsOnHttpServlet() passed");
+ } else {
+ out.println("Authentication results on HttpServletRequest Error.");
+ out.println("request.getAuthType() = " + strAuthType);
+ out.println("request.getRemoteUser() = " + strRemoteUser);
+ if (pp != null) {
+ out.println("request.getUserPrincipal() = " + pp.toString());
+ } else {
+ out.println("request.getUserPrincipal() = null");
+ }
+ }
+ } catch (Exception ex) {
+ System.out.println("ModTestServlet->MTSAuthenResultsOnHttpServlet() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ } // MTSAuthenResultsOnHttpServlet()
+
+ /*
+ * This is basically the same thing as MTSAuthenResultsOnHttpServlet() but we are returning slightly different return
+ * values so...
+ */
+ public void testAuthenAfterLogout(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->testAuthenAfterLogout()");
+ debug("In ModTestServlet->testAuthenAfterLogout()");
+
+ // after successful login, we must get a non-null
+ // value for getUserPrincipal()
+ Principal pp = request.getUserPrincipal();
+
+ if (pp != null) {
+ // good - pp was not null which indicates successful authN
+ out.println("ModTestServlet->testAuthenAfterLogout() passed");
+ } else {
+ // oh oh - we got null pp which indicates we are not authenticated
+ out.println("testAuthenAfterLogout() failed - getUserPrincipal() returned null.");
+ }
+ } catch (Exception ex) {
+ debug("ModTestServlet->testAuthenAfterLogout() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ }
+
+ /*
+ * This will get called after we have authenticated with our user j2ee in role Administrator. When we get into this test
+ * method, a call to isUserInRole better return true. if we have not authenticated, we expect to get false.
+ */
+ public void MTSAuthenIsUserInRole(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->MTSAuthenIsUserInRole()");
+ System.out.println("In ModTestServlet->MTSAuthenIsUserInRole()");
+
+ // after successful login, we should see true value for isUserInRole
+ boolean bval = request.isUserInRole("Administrator");
+
+ if (bval == true) {
+ debug(out, "isUserInRole() returns true.");
+ out.println("ModTestServlet->testAuthenIsUserInRole() passed");
+ } else {
+ debug(out, "Authentication Error - isUserInRole() returns false.");
+ debug(out, "request.getRemoteUser() = " + request.getRemoteUser());
+ Principal pp = request.getUserPrincipal();
+ if (pp != null) {
+ debug(out, "request.getUserPrincipal().getName() = " + pp.getName());
+ } else {
+ debug(out, "request.getUserPrincipal() == null");
+ }
+ out.println("ModTestServlet->MTSAuthenIsUserInRole() failed");
+ }
+ } catch (Exception ex) {
+ System.out.println("ModTestServlet->MTSAuthenIsUserInRole() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ } // MTSAuthenIsUserInRole()
+
+ /*
+ * (Per jsr-196 spec v1.1 section 3.8.4) This will get called after we have authenticated with our user j2ee in role
+ * Administrator. When we get into this test method, a call to getUserPrincipal(), getRemoteUser(), and to
+ * getUserPrincipal().getName() should all CORRESPOND. "Correspond" is not a hard term as it implies there could be some
+ * user mappings involved.
+ *
+ * (Using Servlet spec v3.1, section 13.3 - it states: "The getRemoteUser method returns the name of the remote user"
+ * AND "Calling the getName method on the Principal returned by getUserPrincipal returns the name of the remote user."
+ * We can use these two Servlet spec references combined with our JASPIC reference to validate that principal.getName()
+ * equals the same value returned by getRemoteUser().
+ */
+ public void MTSRemoteUserCorrespondsToPrin(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->MTSRemoteUserCorrespondsToPrin()");
+ System.out.println("In ModTestServlet->MTSRemoteUserCorrespondsToPrin()");
+
+ // after successful login, we should see true value for isUserInRole
+ String strRemoteUser = request.getRemoteUser();
+ Principal pp = request.getUserPrincipal();
+ String prinName = null;
+ if (pp != null) {
+ prinName = pp.getName();
+ }
+
+ if ((prinName != null) && (strRemoteUser != null) && prinName.equals(strRemoteUser)) {
+ out.println("principal.getName() = " + prinName);
+ out.println("request.getRemoteUser() = " + strRemoteUser);
+ out.println("ModTestServlet->testRemoteUserCorrespondsToPrin() passed");
+ } else {
+ out.println("ModTestServlet->MTSRemoteUserCorrespondsToPrin() failed");
+ out.println("principal.getName() = " + prinName);
+ out.println("request.getRemoteUser() = " + strRemoteUser);
+ if (pp != null) {
+ out.println("request.getUserPrincipal().toString() = " + pp.toString());
+ } else {
+ out.println("request.getUserPrincipal() = null");
+ }
+ }
+
+ } catch (Exception ex) {
+ System.out.println("ModTestServlet->MTSRemoteUserCorrespondsToPrin() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ } // MTSRemoteUserCorrespondsToPrin()
+
+ /*
+ * This will get called after we have authenticated with our user j2ee in role Administrator. When we get into this test
+ * method, a call to isUserInRole better return true. if we have not authenticated, we expect to get false.
+ */
+ public void testGPCIsUserInRole(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ boolean bval = false;
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->testGPCIsUserInRole()");
+
+ // first make sure user is in role!
+ // after successful login, we should see true value for isUserInRole
+ bval = request.isUserInRole("Administrator");
+ if (bval == true) {
+ debug(out, "isUserInRole() returns true.");
+ } else {
+ debug(out, "Authentication Error - isUserInRole() returns false.");
+ debug(out, "request.getRemoteUser() = " + request.getRemoteUser());
+ out.println("ModTestServlet->testGPCIsUserInRole() failed");
+ }
+
+ if (bval) {
+ out.println("ModTestServlet->testGPCIsUserInRole() passed");
+ }
+
+ } catch (Exception ex) {
+ System.out.println("ModTestServlet->testGPCIsUserInRole() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ }
+
+ /*
+ * This will get called after we have authenticated with our user j2ee in role Administrator. When we get into this test
+ * method, a call to isUserInRole better return true. if we have not authenticated, we expect to get false.
+ */
+ public void testGPCGetUserPrincipal(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ boolean bval = false;
+
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->testGPCGetUserPrincipal()");
+
+ // getUserPrincipal() should have been set on proper validateRequest()
+ if (request.getUserPrincipal() == null) {
+ debug(out, "ERROR - request.getUserPrincipal() == null but should not!");
+ }
+
+ String principalName = request.getUserPrincipal().getName();
+ if (principalName != null) {
+ debug(out, "request.getUserPrincipal().getName() = " + principalName);
+ bval = true;
+ } else {
+ debug(out, "ERROR - request.getUserPrincipal().getName() == null but should not be");
+ out.println("ModTestServlet->testGPCGetUserPrincipal() failed");
+ }
+
+ if (bval) {
+ out.println("ModTestServlet->testGPCGetUserPrincipal() passed");
+ }
+
+ } catch (Exception ex) {
+ System.out.println("ModTestServlet->testGPCGetUserPrincipal() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ }
+
+ /*
+ * This will get called after we have authenticated with our user j2ee in role Administrator. When we get into this test
+ * method, a call to isUserInRole better return true. if we have not authenticated, we expect to get false.
+ */
+ public void testGPCGetRemoteUser(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ boolean bval = false;
+
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->testGPCGetRemoteUser()");
+
+ // getRemoteUser() should have been set on proper validateRequest()
+ String remoteUser = request.getRemoteUser();
+ if (remoteUser != null) {
+ debug(out, "request.getRemoteUser() = " + remoteUser);
+ bval = true;
+ } else {
+ debug(out, "ERROR - request.getRemoteUser() == null but should not be");
+ out.println("ModTestServlet->testGPCGetRemoteUser() failed");
+ }
+
+ if (bval) {
+ out.println("ModTestServlet->testGPCGetRemoteUser() passed");
+ }
+
+ } catch (Exception ex) {
+ System.out.println("ModTestServlet->testGPCGetRemoteUser() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ }
+
+ /*
+ * This will get called after we have authenticated with our user j2ee in role Administrator. When we get into this test
+ * method, a call to isUserInRole better return true. if we have not authenticated, we expect to get false.
+ */
+ public void testGPCGetAuthType(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ boolean bval = false;
+
+ PrintWriter out = response.getWriter();
+ out.println("Enterred ModTestServlet->testGPCGetAuthType()");
+ debug("enterred ModTestServlet->testGPCGetAuthType()");
+
+ // getAuthType() should have been set on proper validateRequest()
+ String authType = request.getAuthType();
+ if (authType != null) {
+ debug(out, "request.getAuthType() = " + authType);
+ bval = true;
+ } else {
+ debug(out, "ERROR - request.getAuthType() == null but should not be");
+ out.println("ModTestServlet->testGPCGetAuthType() failed");
+ }
+
+ if (bval) {
+ out.println("ModTestServlet->testGPCGetAuthType() passed");
+ }
+
+ } catch (Exception ex) {
+ System.out.println("ModTestServlet->testGPCGetAuthType() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ }
+
+ public void debug(PrintWriter out, String str) {
+ out.println(str);
+ System.out.println(str);
+ }
+
+ public void debug(String str) {
+ System.out.println(str);
+ }
+
+}
diff --git a/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/OpenToAllServlet.java b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/OpenToAllServlet.java
new file mode 100644
index 0000000..a21ef11
--- /dev/null
+++ b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/OpenToAllServlet.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.ServletSecurity;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.security.Principal;
+
+@ServletSecurity
+@WebServlet(name = "OpenToAllServlet", urlPatterns = { "/OpenToAllServlet" })
+public class OpenToAllServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1l;
+
+ private String logFileLocation;
+ private String servletAppContext = null;
+ private String providerConfigFileLocation;
+ private String testMethod = null;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ doPost(request, response);
+ debug("Enterred OpenToAllServlet->doGet()");
+ }
+
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ debug("Enterred OpenToAllServlet->doPost()");
+
+ doTests(request, response);
+ }
+
+ public void doTests(HttpServletRequest request, HttpServletResponse response) {
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ } catch (Exception ex) {
+ debug("got exception in ModTestServlet");
+ ex.printStackTrace();
+ }
+
+ // get some common props that are passed into our servlet request
+ getPropsAndParams(request, response);
+
+ if (testMethod.equals("testGPCWithNoRequiredAuth")) {
+ TestGPCWithNoRequiredAuth(request, response);
+ } else if (testMethod.equals("testAuthenAfterLogout")) {
+ TestAuthenAfterLogout(request, response);
+ } else {
+ // if here, it most likely means that we ran a test from within
+ // Client.java which
+ // invoked this servlet with the only intent being to check if access
+ // could be
+ // made. Some tests only care that they can access this servlet and do NOT
+ // need to run any particular testMethod in here.
+ debug("WARNING: OpenToAllServlet.doTests() testMethod not recognized: " + testMethod);
+ }
+ }
+
+ public void TestAuthenAfterLogout(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ PrintWriter out = response.getWriter();
+ System.out.println("In OpenToAllServlet->TestAuthenAfterLogout()");
+
+ Principal pp = request.getUserPrincipal();
+ if (pp != null) {
+ // ohoh - when no authN required for this servlet, we are detecting
+ // that some authentication occurred -OR- that we are pre-logged in
+ // either way, thats a problem so force a logout.
+ out.println("OpenToAllServlet: we should not be authenticated so forcing logout");
+ request.logout();
+ } else {
+ out.println("OpenToAllServlet: pp == null so we were not pre-logged in.");
+ out.println("no need to force a logout since we are (correctly) not logged in.");
+ }
+ } catch (Exception ex) {
+ System.out.println("OpenToAllServlet->TestAuthenAfterLogout() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ /*
+ * This will get called after we have authenticated with our user j2ee in role Administrator. When we get into this test
+ * method, a call to isUserInRole better return true. if we have not authenticated, we expect to get false.
+ */
+ public void TestGPCWithNoRequiredAuth(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ PrintWriter out = response.getWriter();
+ out.println("Enterred OpenToAllServlet->TestGPCWithNoRequiredAuth()");
+ System.out.println("In OpenToAllServlet->TestGPCWithNoRequiredAuth()");
+
+ // after successful login, we should see true value for isUserInRole
+ boolean bval = request.isUserInRole("Administrator");
+
+ if (bval == true) {
+ debug(out, "isUserInRole() returns true.");
+ debug("OpenToAllServlet->testAuthenIsUserInRole() isUserInRole() returns true");
+ } else {
+ debug("OpenToAllServlet->TestGPCWithNoRequiredAuth() isUserInRole() returns false");
+ }
+ out.println("OpenToAllServlet->testAuthenIsUserInRole() passed");
+
+ } catch (Exception ex) {
+ System.out.println("OpenToAllServlet->TestGPCWithNoRequiredAuth() failed");
+ ex.printStackTrace();
+ }
+
+ return;
+ }
+
+ // this pulls out some params that are passed in on our servlet req
+ // that is made from within the client code (e.g. Client.java).
+ private void getPropsAndParams(HttpServletRequest req, HttpServletResponse response) {
+
+ // set logfile location
+ logFileLocation = req.getParameter("log.file.location");
+ if ((logFileLocation != null) && (-1 < logFileLocation.indexOf(JASPICData.DEFAULT_LOG_FILE))) {
+ // if here, we have logfile location value which contains
+ // JASPICData.DEFAULT_LOG_FILE
+ debug("logFileLocation already set");
+ } else if (logFileLocation != null) {
+ debug("logFileLocation NOT set completely");
+ System.setProperty("log.file.location", logFileLocation);
+ } else {
+ debug("ModTestServlet: logFileLocation null");
+ }
+ debug("logFileLocation = " + logFileLocation);
+
+ // set provider config file
+ providerConfigFileLocation = req.getParameter("provider.configuration.file");
+ debug("TS Provider ConfigFile = " + providerConfigFileLocation);
+ if (providerConfigFileLocation == null) {
+ debug("ERROR: getPropsAndParams(): providerConfigFileLocation = null");
+ } else {
+ debug("getPropsAndParams(): providerConfigFileLocation = " + providerConfigFileLocation);
+ }
+
+ // set testMethod
+ testMethod = req.getParameter("method.under.test");
+
+ servletAppContext = IdUtil.getAppContextId(JASPICData.LAYER_SERVLET);
+
+ return;
+ }
+
+ public void debug(PrintWriter out, String str) {
+ out.println(str);
+ System.out.println(str);
+ }
+
+ public void debug(String str) {
+ System.out.println(str);
+ }
+
+}
diff --git a/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/OptionalAuthen.java b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/OptionalAuthen.java
new file mode 100644
index 0000000..83d6d59
--- /dev/null
+++ b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/OptionalAuthen.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import jakarta.annotation.security.DeclareRoles;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.HttpMethodConstraint;
+import jakarta.servlet.annotation.ServletSecurity;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+@DeclareRoles({ "Administrator", "Manager", "Employee" })
+@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET"), @HttpMethodConstraint(value = "POST") })
+@WebServlet(urlPatterns = { "/OptionalAuthen", "/ModuleAuthStatusThrowExNoDispatch" })
+public class OptionalAuthen extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ PrintWriter out = response.getWriter();
+ doPost(request, response);
+ out.println("Enterred OptionalAuthen->doGet()");
+ }
+
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ System.out.println("In OptionalAuthen->doPost()");
+
+ PrintWriter out = response.getWriter();
+ out.println("Enterred OptionalAuthen->doPost()");
+
+ out.println("request.getRequestURI() = " + request.getRequestURI());
+ out.println("request.getServletPath() = " + request.getServletPath());
+ out.println("request.getPathInfo() = " + request.getPathInfo());
+ out.println("request.getMethod() = " + request.getMethod());
+ }
+
+ @Override
+ public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ System.out.println("In OptionalAuthen->service()");
+ PrintWriter out = response.getWriter();
+ out.println("Enterred OptionalAuthen->service()");
+ doPost(request, response);
+ }
+
+}
diff --git a/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/WrapperServlet.java b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/WrapperServlet.java
new file mode 100644
index 0000000..24d0380
--- /dev/null
+++ b/tck/spi/servlet/src/main/java/ee/jakarta/tck/authentication/test/basic/servlet/WrapperServlet.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.servlet;
+
+import static java.util.logging.Level.INFO;
+
+import ee.jakarta.tck.authentication.test.common.logging.server.TSLogger;
+import jakarta.annotation.security.DeclareRoles;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.annotation.HttpConstraint;
+import jakarta.servlet.annotation.HttpMethodConstraint;
+import jakarta.servlet.annotation.ServletSecurity;
+import jakarta.servlet.annotation.WebServlet;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+@DeclareRoles({ "Administrator", "Manager", "Employee" })
+@ServletSecurity(value = @HttpConstraint(rolesAllowed = { "Administrator" }), httpMethodConstraints = {
+ @HttpMethodConstraint(value = "GET", rolesAllowed = "Administrator"),
+ @HttpMethodConstraint(value = "POST", rolesAllowed = "Administrator") })
+@WebServlet(name = "WrapperServlet", urlPatterns = { "/WrapperServlet" })
+public class WrapperServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ private String providerConfigFileLocation;
+ private String vendorACFClass;
+ private String testMethod;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ doTests(request, response);
+ }
+
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ doTests(request, response);
+ }
+
+ public void doTests(HttpServletRequest request, HttpServletResponse response) {
+ debug("in WrapperServlet.doTests");
+
+ TSLogger logger = TSLogger.getTSLogger();
+
+ // get some common props
+ getPropsAndParams(request, response);
+
+ //
+ // now send string out to logger so we can verify that the content
+ // gets processed BEFORE secureResponse.
+ debug("in WrapperServlet.doTests: calling logger.log()");
+ logger.log(INFO, "WrapperServlet.doTests() content processed for requestURI");
+
+ if (testMethod.equals("testRequestWrapper")) {
+ testRequestWrapper(request, response);
+ } else if (testMethod.equals("testResponseWrapper")) {
+ testResponseWrapper(request, response);
+ }
+
+ // Restore original (CTS) factory class
+ // note: this should be done in many of the calls but its a safety measure
+ // to ensure we are resetting things back to expected defaults
+ try {
+ CommonUtils.resetDefaultACF();
+ } catch (Exception ex) {
+ debug("ACFTestServlet: error calling CommonUtils.resetDefaultACF(): " + ex.getMessage());
+ ex.printStackTrace();
+ }
+ }
+
+ private void getPropsAndParams(HttpServletRequest req, HttpServletResponse response) {
+ // set provider config file
+ providerConfigFileLocation = System.getProperty("provider.configuration.file");
+ debug("TS Provider ConfigFile = " + providerConfigFileLocation);
+ if (providerConfigFileLocation == null) {
+ debug("ERROR: getPropsAndParams(): providerConfigFileLocation = null");
+ } else {
+ debug("getPropsAndParams(): providerConfigFileLocation = " + providerConfigFileLocation);
+ }
+
+ // set testMethod
+ testMethod = req.getParameter("method.under.test");
+
+ // set vendor class
+ vendorACFClass = System.getProperty("vendor.authconfig.factory");
+ if (vendorACFClass == null) {
+ debug("ERROR: getPropsAndParams(): vendorACFClass = null");
+ } else {
+ debug("getPropsAndParams(): vendorACFClass = " + vendorACFClass);
+ }
+
+ return;
+ }
+
+ public void testRequestWrapper(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ PrintWriter out = response.getWriter();
+ out.println("WrapperServlet->testRequestWrapper()");
+ out.println("isRequestWrapped = " + request.getAttribute("isRequestWrapped"));
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("WrapperServlet->testRequestWrapper() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ public void testResponseWrapper(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ PrintWriter out = response.getWriter();
+ out.println("WrapperServlet->testResponseWrapper()");
+ out.println("isResponseWrapped = " + response.getHeader("isResponseWrapped"));
+ out.flush();
+ } catch (Exception ex) {
+ System.out.println("WrapperServlet->testResponseWrapper() failed");
+ ex.printStackTrace();
+ }
+ }
+
+ public void debug(String str) {
+ System.out.println(str);
+ }
+
+}
diff --git a/tck/spi/servlet/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer b/tck/spi/servlet/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer
new file mode 100644
index 0000000..7a4388c
--- /dev/null
+++ b/tck/spi/servlet/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer
@@ -0,0 +1 @@
+ee.jakarta.tck.authentication.test.basic.servlet.AuthFactoryContainerInitializer
\ No newline at end of file
diff --git a/tck/spi/servlet/src/main/webapp/WEB-INF/web.xml b/tck/spi/servlet/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..180833e
--- /dev/null
+++ b/tck/spi/servlet/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ spi_servlet
+
+
+ BASIC
+ default
+
+
+
diff --git a/tck/spi/servlet/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletProfileSPITest.java b/tck/spi/servlet/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletProfileSPITest.java
new file mode 100644
index 0000000..48c8b7e
--- /dev/null
+++ b/tck/spi/servlet/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletProfileSPITest.java
@@ -0,0 +1,2185 @@
+package ee.jakarta.tck.authentication.test.basic;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import ee.jakarta.tck.authentication.test.basic.servlet.AuthFactoryContainerInitializer;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.common.ArquillianBase;
+import ee.jakarta.tck.authentication.test.common.logging.client.LogFileProcessor;
+import jakarta.servlet.ServletContainerInitializer;
+import org.htmlunit.WebResponse;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests a large number of SPI assertions from the Servlet profile.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class ServletProfileSPITest extends ArquillianBase {
+
+ // this must be the decoded context path corresponding to the web module
+ private String contextPath = "/" + JASPICData.SCP_CONTEXT_PATH;
+ private String servletPath = "ModTestServlet";
+ private String acfServletPath = "ACFTestServlet";
+ private String wrapperServletPath = "WrapperServlet";
+ private String openToAllServletPath = "OpenToAllServlet";
+ private String allAccessServletPath = openToAllServletPath;
+ private String staticPagePath = "client.html";
+ private String noConstraintPath = "OptionalAuthen";
+
+ private String appContext = System.getProperty("logical.hostname.servlet") + " " + contextPath;
+ private String ACF_MSG_1 = "TSAuthConfigFactory.getConfigProvider " + "returned non-null provider for Layer : HttpServlet" + " and AppContext :" + appContext;
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ WebArchive archive = defaultWebArchive("spitests_servlet_web");
+ archive.addAsServiceProvider(ServletContainerInitializer.class, AuthFactoryContainerInitializer.class);
+
+ System.out.println(archive.toString(true));
+
+ return archive;
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckSecureRespForOptionalAuth
+ *
+ * @assertion_ids: JASPIC:SPEC:59; JASPIC:SPEC:304; JASPIC:JAVADOC:27;
+ * JASPIC:JAVADOC:10; JASPIC:JAVADOC:11; JASPIC:JAVADOC:28;
+ * JASPIC:JAVADOC:13;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify secureResponse was called.
+ *
+ * Description This method will make a URL post that has
+ * optional security Authen which means that we should NOT
+ * need to set any principals in the validateRequest methods
+ * nor the callbacks. The Runtime should allow this to proceed
+ * to call the secureResponse even though there is no
+ * principal values explicitly being set. Note: we need to
+ * specifically hardwire the particular context used in this
+ * test to NOT have any principals set on the server side.
+ *
+ */
+ @Test
+ public void CheckSecureRespForOptionalAuth() {
+ getFromServerPath("OptionalAuthen");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "HttpServlet profile with servletName=/" +
+ "OptionalAuthen returning AuthStatus=AuthStatus.SUCCESS"));
+
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "secureResponse called for layer=HttpServlet for requestURI=" +
+ contextPath + "/OptionalAuthen"));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckSecureRespForMandatoryAuth
+ *
+ * @assertion_ids: JASPIC:SPEC:98; JASPIC:SPEC:304; JASPIC:JAVADOC:26;
+ * JASPIC:JAVADOC:31; JASPIC:JAVADOC:10; JASPIC:JAVADOC:9;
+ * JASPIC:SPEC:103;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify secureResponse and CallerPrincipalCallback are
+ * called.
+ *
+ * Description This method will make a URL post that has
+ * Mandatory security Authen which means that we need to set a
+ * principal objects in the validateRequest method
+ * clientSubject object (or in a callback). Either way, once
+ * we set a principal object in the clientSubject - The
+ * Runtime should proceed to call the secureResponse and
+ * should invoke the CallbackHandler passed to it by the
+ * runtime to handle a CallerPrincipalCallback using the
+ * clientSubject as argument to it. For this case, we want to
+ * ensure the following occur: - AuthStatus returns SUCCESS
+ * (we know this is occuriing otherwise we would not make it
+ * into secureResponse) - isMandatory() == true -
+ * secureResponse is called - CallerPrincipalCallback handler
+ * gets invoked.
+ *
+ * NOTE: We need our server side to check and ensure there are
+ * principal values being set for this particular context
+ * posting.
+ *
+ */
+ @Test
+ public void CheckSecureRespForMandatoryAuth() {
+ String strHDR = "HttpServlet profile with servletName=/";
+ String theContext = contextPath + "/" + JASPICData.AUTHSTAT_MAND_SUCCESS;
+
+ String strMsg1 = strHDR + JASPICData.AUTHSTAT_MAND_SUCCESS
+ + " returning AuthStatus=AuthStatus.SUCCESS";
+ String strMsg2 = "secureResponse called for layer=HttpServlet for requestURI="
+ + theContext;
+ String strMsg3 = "In HttpServlet : ServerRuntime CallerPrincipalCallback";
+ strMsg3 += " called for profile=HttpServlet for servletPath=" + theContext;
+
+ getFromServerPath(JASPICData.AUTHSTAT_MAND_SUCCESS);
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(
+ logProcessor.verifyLogContains(
+ strMsg1, strMsg2, strMsg3));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testSecRespCalledAfterSvcInvoc
+ *
+ * @assertion_ids: JASPIC:SPEC:108;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify secureResponse and CallerPrincipalCallback are
+ * called.
+ *
+ * Description This method will make a URL post that has
+ * Mandatory security Authen and it will verify that the
+ * secureResponse() method has NOT been called before the
+ * servlet/service invocation by checking for the existance of
+ * a cts proprietary request property that would only get set
+ * from in secureResponse. So if the property is found, we
+ * know a call to secureResponse was incorrectly made BEFORE
+ * the servlet/service invocation but if the request property
+ * is NOT found, then we can assume that secureResponse was
+ * NOT called before the servlet/service invocation.
+ *
+ */
+ @Test
+ public void testSecRespCalledAfterSvcInvoc() {
+ String response = getFromServerPath(
+ JASPICData.AUTHSTAT_MAND_SUCCESS + "?" + "method.under.test=" + "testSecRespCalledAfterSvcInvoc");
+
+ assertTrue(response.contains("testSecRespCalledAfterSvcInvoc() passed"));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckNoAuthReturnsValidStatusCode
+ *
+ * @assertion_ids: JASPIC:SPEC:93
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Make servlet invocations and check the return status to
+ * verify proper server side handling.
+ *
+ * Description This method will make a request that is not
+ * authorized and then verify that the status code returned is
+ * not indicating the request was OK==200. If we get back a
+ * statuscode = 200 then there was a problem since we were
+ * trying to access a page that had mandatory authentication
+ * set AND we were trying to use an invalid user/pwd to
+ * perform that access - thus we should NOT get an okay status
+ * code returned since our bad username/pwd will not have
+ * perms.
+ *
+ */
+ @Test
+ public void CheckNoAuthReturnsValidStatusCode() {
+ // invokeServlet will attempt to access the resource that does
+ // not have the proper role creds assigned to it
+ // thus we expect a return status code != 200
+ WebResponse response = responseFromServerWithCredentials("AnotherMandatoryAuthen", "j2ee", "j2ee");
+
+ // if status of 200 was returned then there is a problem since
+ // we should have been forbidden from completing our request
+ // as our username/pwd change means we should not be authenticated
+ assertTrue(response.getStatusCode() != 200);
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: VerifyRequestDispatchedProperly
+ *
+ * @assertion_ids: JASPIC:SPEC:317; JASPIC:JAVADOC:27; JASPIC:JAVADOC:28;
+ *
+ *
+ * @test_Strategy: 1. issue request that has mandatory auth and verify it gets
+ * authorized.
+ *
+ * 2. issue a request that is mandatory but NOT
+ * authorized (eg submit request with invalid user/pwd) and
+ * verify that secureResponse is still called by MPR.
+ *
+ * Description The request must be dispatched to the resource
+ * if the request was determined to be authorized; otherwise
+ * it must NOT be dispatched and the runtime must proceed to
+ * point (3) in the message processing model.
+ *
+ */
+ @Test
+ public void VerifyRequestDispatchedProperly() {
+ // we should see that our request is properly dispatched
+ // we will assume that a proper response code indicates success
+ // as we are using correct creds
+ WebResponse response = responseFromServerWithCredentials(
+ JASPICData.AUTHSTAT_MAND_SUCCESS +
+ "?method.under.test=VerifyRequestDispatchedProperly", "j2ee", "j2ee");
+
+ assertTrue(response.getStatusCode() == 200);
+
+ // invokeServlet will attempt to access the resource that
+ // does not have proper role creds assigned
+ // thus we expect a return status code != 200
+ response = responseFromServerWithCredentials("AnotherMandatoryAuthen", "j2ee", "j2ee");
+
+ assertTrue(response.getStatusCode() != 200);
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Now verify that the MPR went into the secureResponse
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "secureResponse called for layer=HttpServlet for requestURI=" +
+ (getBase().getPath() + JASPICData.AUTHSTAT_MAND_SUCCESS)));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckValidateReqAuthException
+ *
+ * @assertion_ids: JASPIC:SPEC:58; JASPIC:SPEC:320; JASPIC:SPEC:94;
+ * JASPIC:JAVADOC:1; JASPIC:JAVADOC:28;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify secureResponse was not called for the given context
+ * and that an AuthException was called.
+ *
+ * Description This method will make a URL post using a
+ * context that should cause an AuthException to get thrown
+ * from the validateRequest. This should cause the
+ * secureResponse to NOT get called.
+ *
+ */
+ @Test
+ public void CheckValidateReqAuthException() {
+ WebResponse response = responseFromServerWithCredentials(
+ JASPICData.AUTHSTAT_THROW_EX_ND, "j2ee", "j2ee");
+
+ assertTrue(
+ response.getStatusCode() == 403 ||
+ response.getStatusCode() == 404 ||
+ response.getStatusCode() == 500);
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "HttpServlet profile with servletName=/" +
+ JASPICData.AUTHSTAT_THROW_EX_ND + " returning AuthStatus=AuthException"));
+
+ // Also verify that no call to secureResponse was made
+ assertFalse(
+ logProcessor.verifyLogContains(
+ "secureResponse called for layer=HttpServlet for requestURI=" +
+ contextPath + "/" + JASPICData.AUTHSTAT_THROW_EX_ND));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckValidateReqAlwaysCalled
+ *
+ * @assertion_ids: JASPIC:SPEC:58; JASPIC:SPEC:320; JASPIC:SPEC:89;
+ * JASPIC:SPEC:94; JASPIC:JAVADOC:1; JASPIC:JAVADOC:28;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify secureResponse was not called for the given context
+ * and that an AuthException was called.
+ *
+ * Description This method will make mulitple posts using
+ * contexts w/ authN that is both required and non-required.
+ * We want to confirm that validateRequest is called
+ * independent of whether authN is required (i.e. including
+ * when isMandatory() would be false). Among other things,
+ * This is validating JASPIC spec section 3.8 which states
+ * "validateRequest must be called for all requests".
+ *
+ */
+ @Test
+ public void CheckValidateReqAlwaysCalled() {
+ responseFromServerWithCredentials(
+ "ModTestServlet" + "?method.under.test=CheckValidateReqAlwaysCalled", "j2ee", "j2ee");
+
+ responseFromServerWithCredentials(
+ "OptionalAuthen" + "?method.under.test=CheckValidateReqAlwaysCalled", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContains(
+ "validateRequest() called for " + contextPath + "/ModTestServlet" + ", isMandatory() = true"));
+
+ assertTrue(logProcessor.verifyLogContains(
+ "validateRequest() called for " + contextPath + "/OptionalAuthen" + ", isMandatory() = false"));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: AuthConfigFactoryGetFactory
+ *
+ * @assertion_ids: JASPIC:SPEC:7; JASPIC:SPEC:10; JASPIC:JAVADOC:84;
+ * JASPIC:JAVADOC:94; JASPIC:JAVADOC:79; JASPIC:JAVADOC:97;
+ * JASPIC:JAVADOC:77; JASPIC:JAVADOC:80; JASPIC:JAVADOC:84;
+ * JASPIC:JAVADOC:85;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify Whether AuthConfigFactory.getFactory is called and
+ * instantiated in the server.
+ *
+ * Description The AuthConfigFactory.getFactory method must be
+ * used during the container bootstrap processs.
+ *
+ */
+ @Test
+ public void AuthConfigFactoryGetFactory() {
+ responseFromServerWithCredentials(
+ "ModTestServlet" + "?method.under.test=AuthConfigFactoryGetFactory", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContains(
+ "TSAuthConfigFactory.getFactory called Indirectly"));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: GetConfigProvider
+ *
+ * @assertion_ids: JASPIC:SPEC:8; JASPIC:SPEC:14; JASPIC:JAVADOC:79;
+ * JASPIC:JAVADOC:84; JASPIC:JAVADOC:85; JASPIC:JAVADOC:91
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify Whether AuthConfigFactory.getConfigProvider is
+ * called in the server.
+ *
+ * Description The runtime must invoke
+ * AuthConfigFactory.getConfigProvider to obtain the
+ * AuthConfigProvider.
+ *
+ */
+ @Test
+ public void GetConfigProvider() {
+ responseFromServerWithCredentials(
+ "ModTestServlet" + "?method.under.test=GetConfigProvider", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContains(
+ "TSAuthConfigFactory.getConfigProvider called"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckAuthContextId
+ *
+ * @assertion_ids: JASPIC:SPEC:80
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify that the authentication context identifier used in
+ * the call to getAuthContext is equivalent to the value that
+ * is acquired in the call to getAuthContextID with the
+ * MessageInfo that is be used in the call to validateRequest.
+ *
+ * Description The authentication context identifier used in
+ * the call to getAuthContext must be equivalent to the value
+ * that would be acquired by calling getAuthContextID with the
+ * MessageInfo that will be used in the call to
+ * validateRequest.
+ *
+ */
+ @Test
+ public void CheckAuthContextId() {
+ responseFromServerWithCredentials(
+ "ModTestServlet" + "?method.under.test=CheckAuthContextId", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContains(
+ "getAuthContextID() called for layer=HttpServlet shows"+ " AuthContextId=/ModTestServlet GET",
+
+ "TSServerAuthConfig.getAuthContext: layer=HttpServlet" +
+ " : appContext=" + System.getProperty("logical.hostname.servlet") + " " + contextPath +
+ " operationId=/ModTestServlet GET"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: AuthConfigFactoryRegistration
+ *
+ * @assertion_ids: JASPIC:SPEC:80;
+ *
+ * @test_Strategy: this was originally in register directory but was moved
+ * here and the code pulled out and centralized into
+ * ACFTestServlet.
+ *
+ */
+ @Test
+ public void AuthConfigFactoryRegistration() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=AuthConfigFactoryRegistration", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->AuthConfigFactoryRegistration() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFInMemoryNotifyOnUnReg
+ *
+ * @assertion_ids: JASPIC:SPEC:336; JASPIC:SPEC:337; JASPIC:SPEC:338;
+ * JASPIC:SPEC:339; JASPIC:SPEC:342; JASPIC:SPEC:344;
+ *
+ * @test_Strategy: this was originally in register directory but was moved
+ * here and the code pulled out and centralized into
+ * ACFTestServlet.
+ *
+ */
+ @Test
+ public void ACFInMemoryNotifyOnUnReg() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFInMemoryNotifyOnUnReg", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFInMemoryNotifyOnUnReg() passed"));
+
+ }
+
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFPersistentNotifyOnUnReg
+ *
+ * @assertion_ids: JASPIC:SPEC:336; JASPIC:SPEC:337; JASPIC:SPEC:338;
+ * JASPIC:SPEC:339; JASPIC:SPEC:341; JASPIC:SPEC:344;
+ *
+ * @test_Strategy: this was originally in register directory but was moved
+ * here and the code pulled out and centralized into
+ * ACFTestServlet.
+ *
+ */
+ @Test
+ public void ACFPersistentNotifyOnUnReg() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFPersistentNotifyOnUnReg", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFPersistentNotifyOnUnReg() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFInMemoryPrecedenceRules
+ *
+ * @assertion_ids: JASPIC:SPEC:328; JASPIC:SPEC:337; JASPIC:SPEC:338;
+ * JASPIC:SPEC:338; JASPIC:SPEC:339; JASPIC:SPEC:344;
+ *
+ * @test_Strategy: this was originally in register directory but was moved
+ * here and the code pulled out and centralized into
+ * ACFTestServlet.
+ *
+ */
+ @Test
+ public void ACFInMemoryPrecedenceRules() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFInMemoryPrecedenceRules", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFInMemoryPrecedenceRules() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFPersistentPrecedenceRules
+ *
+ * @assertion_ids: JASPIC:SPEC:328; JASPIC:SPEC:337; JASPIC:SPEC:338;
+ * JASPIC:SPEC:338; JASPIC:SPEC:339; JASPIC:SPEC:344;
+ *
+ * @test_Strategy: this was originally in register directory but was moved
+ * here and the code pulled out and centralized into
+ * ACFTestServlet.
+ *
+ */
+ @Test
+ public void ACFPersistentPrecedenceRules() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFPersistentPrecedenceRules", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFPersistentPrecedenceRules() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFGetRegistrationContext
+ *
+ * @assertion_ids: JASPIC:JAVADOC:81;
+ *
+ * @test_Strategy: This is testing that acf.getRegistrationContext(string)
+ * returns NULL for an unrecognized string. (this requirement
+ * described in javadoc for api)
+ */
+ @Test
+ public void ACFGetRegistrationContext() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFGetRegistrationContext", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFGetRegistrationContext() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFGetRegistrationIDs
+ *
+ * @assertion_ids: JASPIC:JAVADOC:82;
+ *
+ * @test_Strategy: This is testing that acf.getRegistrationIDs(acp) NEVER
+ * returns null hint: this must return empty array even if
+ * unrecognized acp. (this requirement described in javadoc
+ * for api)
+ *
+ */
+ @Test
+ public void ACFGetRegistrationIDs() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFGetRegistrationIDs", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFGetRegistrationIDs() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFRemoveRegistration
+ *
+ * @assertion_ids: JASPIC:JAVADOC:86;
+ *
+ * @test_Strategy: This is testing that acf.removeRegistration(arg) will
+ * return FALSE when invalid arg supplied. (this requirement
+ * described in javadoc for api)
+ *
+ */
+ @Test
+ public void ACFRemoveRegistration() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFRemoveRegistration", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFRemoveRegistration() passed"));
+
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFDetachListener
+ *
+ * @assertion_ids: JASPIC:JAVADOC:78;
+ *
+ * @test_Strategy: This is testing that acf.detachListener(...) will return
+ * non-null when unregistered listener supplied. (this
+ * requirement described in javadoc for api)
+ *
+ */
+ @Test
+ public void ACFDetachListener() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFDetachListener", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFDetachListener() passed"));
+
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFGetFactory
+ *
+ * @assertion_ids: JASPIC:SPEC:329; JASPIC:SPEC:335; JASPIC:SPEC:7;
+ *
+ * @test_Strategy: This s mainly concerned with testing the runtimes handling
+ * of ACF as follows: - get current (CTS) ACF - switch to use
+ * different (CTS) ACF - verify calls to ACF use the
+ * newer/expected ACF - restore original ACF
+ */
+ @Test
+ public void ACFGetFactory() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFGetFactory", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFGetFactory() passed"));
+
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testACFComesFromSecFile
+ *
+ * @assertion_ids: JASPIC:SPEC:329; JASPIC:SPEC:330;
+ *
+ * @test_Strategy: This is calling a method on the server(actually servlet)
+ * side that will invoke getFactory() to verify a non-null
+ * facotry instance is returned. It will also verify that the
+ * authconfigprovider.factory security property is properly
+ * set/used.
+ *
+ */
+ @Test
+ public void testACFComesFromSecFile() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=testACFComesFromSecFile", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->testACFComesFromSecFile() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFPersistentRegisterOnlyOneACP
+ *
+ * @assertion_ids: JASPIC:SPEC:329; JASPIC:SPEC:331; JASPIC:SPEC:332;
+ * JASPIC:SPEC:340; JASPIC:SPEC:341;
+ *
+ * @test_Strategy: This will make a server (actually servlet) side method call
+ * that will do the following: - load vendors ACF -
+ * (persistent) register of CTS ACP's in the vendors ACF - get
+ * list of vendors registered provider ID's - register another
+ * persistent ACP (this is standalone ACP profile) - verify
+ * another regId was added for standalone ACP - try to
+ * re-register (persistently) standalone provider - verify 2nd
+ * attempt at added standalone provider REPLACED the first but
+ * it should NOT have added another nor failed. - also confirm
+ * that regID for standalone ACP stayed the same after 1st and
+ * 2nd attempt to register standalone ACP - verify that the
+ * 2nd re-registering of ACP replaced the ACP AND the
+ * description. - unregister standalone ACP and setFactory
+ * back to CTS default
+ *
+ */
+ @Test
+ public void ACFPersistentRegisterOnlyOneACP() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFPersistentRegisterOnlyOneACP", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFPersistentRegisterOnlyOneACP() passed"));
+
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFInMemoryRegisterOnlyOneACP
+ *
+ * @assertion_ids: JASPIC:SPEC:334; JASPIC:SPEC:342; JASPIC:SPEC:343;
+ *
+ * @test_Strategy: This will make a server (actually servlet) side method call
+ * that will do the following: - load vendors ACF -
+ * (persistent) register of CTS ACP's in the vendors ACF - get
+ * list of vendors registered provider ID's - register
+ * (in-memory) ACP (this is standalone ACP profile) - verify
+ * another regId was added for standalone ACP - try to
+ * re-register (in-memory) standalone provider - verify 2nd
+ * attempt at added standalone provider REPLACED the first but
+ * it should NOT have added another nor failed. - also confirm
+ * that regID for standalone ACP stayed the same after 1st and
+ * 2nd attempt to register standalone ACP - verify that the
+ * 2nd re-registering of ACP replaced the ACP AND the
+ * description. - unregister standalone ACP and setFactory
+ * back to CTS default
+ *
+ */
+ @Test
+ public void ACFInMemoryRegisterOnlyOneACP() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFInMemoryRegisterOnlyOneACP", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFInMemoryRegisterOnlyOneACP() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFUnregisterACP
+ *
+ * @assertion_ids: JASPIC:SPEC:344;
+ *
+ * @test_Strategy: This will make a server (actually servlet) side method call
+ * that will do the following: - load vendors ACF -
+ * (persistent) register of CTS ACP's in the vendors ACF - get
+ * list of vendors registered provider ID's - register
+ * (in-memory) ACP (this is standalone ACP profile) - verify
+ * another regId was added for standalone ACP - unregister the
+ * in-memory ACP we just registered - verify
+ * removeRegistration() method call returned proper boolean -
+ * verify expected # of registry eentries - verify 2nd call to
+ * removeRegistration() with regId that was previously removed
+ * and should expect return val of false
+ *
+ */
+ @Test
+ public void ACFUnregisterACP() {
+ String response = readFromServerWithCredentials(
+ acfServletPath + "?method.under.test=ACFUnregisterACP", "j2ee", "j2ee");
+
+ assertTrue(response.contains("ACFTestServlet->ACFUnregisterACP() passed"));
+
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckACFVerifyPersistence
+ *
+ * @assertion_ids: JASPIC:SPEC:75; JASPIC:SPEC:335;
+ *
+ * @test_Strategy: This tests the (persistent) registration of CTS ACP's
+ * within the the vendors ACF.
+ *
+ */
+ @Test
+ public void CheckACFVerifyPersistence() {
+ String response = readFromServerWithCredentials(
+ acfServletPath, "j2ee", "j2ee");
+
+ assertTrue(response.contains("AuthConfigFactoryVerifyPersistence() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckRegistrationContextId
+ *
+ * @assertion_ids: JASPIC:SPEC:77;
+ *
+ * @test_Strategy: This registers CTS ACP's within vendors ACF and then
+ * verifies the RegistrationContext info can be obtained from
+ * the vendors ACF.
+ *
+ */
+ @Test
+ public void CheckRegistrationContextId() {
+ String response = readFromServerWithCredentials(
+ acfServletPath, "j2ee", "j2ee");
+
+ assertTrue(response.contains("getRegistrationContextId() TSProviders registration passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testRequestWrapper
+ *
+ * @assertion_ids: JASPIC:SPEC:108; JASPIC:SPEC:311;
+ *
+ * @test_Strategy:
+ *
+ * From JASPIC Spec section 3.8.3.5: When a ServerAuthModule
+ * returns a wrapped message in MessageInfo, or unwraps a
+ * message in MessageInfo, the message processing runtime must
+ * ensure that the HttpServletRequest and HttpServletResponse
+ * objects established by the ServerAuthModule are used in
+ * downstream processing.
+ *
+ * This test uses a Server Authentication Module(SAM) that
+ * wraps and unwraps the HttpRequest as specified by the
+ * JASPIC spec and expects the runtime to handle the Wrapped
+ * HttpRequest.
+ *
+ */
+ @Test
+ public void testRequestWrapper() {
+ String response = readFromServerWithCredentials(
+ wrapperServletPath + "?method.under.test=testRequestWrapper", "j2ee", "j2ee");
+
+ assertTrue(response.contains("isRequestWrapped = true"));
+ assertFalse(response.contains("Incorrect request type"));
+
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testResponseWrapper
+ *
+ * @assertion_ids: JASPIC:SPEC:108; JASPIC:SPEC:311;
+ *
+ * @test_Strategy: From JASPIC Spec section 3.8.3.5: When a ServerAuthModule
+ * returns a wrapped message in MessageInfo, or unwraps a
+ * message in MessageInfo, the message processing runtime must
+ * ensure that the HttpServletRequest and HttpServletResponse
+ * objects established by the ServerAuthModule are used in
+ * downstream processing.
+ *
+ * This test uses a Server Authentication Module(SAM) that
+ * wraps and unwraps the HttpResponse as specified by the
+ * JASPIC spec and expects the runtime to handle the Wrapped
+ * HttpResponse.
+ */
+ @Test
+ public void testResponseWrapper() {
+ String response = readFromServerWithCredentials(
+ wrapperServletPath + "?method.under.test=testResponseWrapper", "j2ee", "j2ee");
+
+ assertTrue(response.contains("isResponseWrapped = true"));
+ assertFalse(response.contains("Incorrect request type"));
+
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckCallbackSupport
+ *
+ * @assertion_ids: JASPIC:SPEC:72; JASPIC:SPEC:103; JASPIC:JAVADOC:27; JASPIC:JAVADOC:40; JASPIC:JAVADOC:46;
+ * JASPIC:JAVADOC:31; JASPIC:JAVADOC:32; JASPIC:JAVADOC:33; JASPIC:JAVADOC:34; JASPIC:JAVADOC:38; JASPIC:JAVADOC:39;
+ * JASPIC:JAVADOC:41; JASPIC:JAVADOC:42; JASPIC:JAVADOC:43; JASPIC:JAVADOC:44; JASPIC:JAVADOC:35; JASPIC:JAVADOC:36;
+ * JASPIC:JAVADOC:51; JASPIC:JAVADOC:49; JASPIC:JAVADOC:54; JASPIC:JAVADOC:65; JASPIC:JAVADOC:63; JASPIC:JAVADOC:68;
+ * JASPIC:JAVADOC:69; JASPIC:JAVADOC:71; JASPIC:JAVADOC:28; JASPIC:JAVADOC:107;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to verify Whether the following callbackHandlers are supported:
+ * CallerPrincipalCallback, GroupPrincipalCallback, and PasswordValidationCallback.
+ *
+ * Description The CallbackHandler passed to ServerAuthModule.initialize must support the following callbacks:
+ * CallerPrincipalCallback, GroupPrincipalCallback, and PasswordValidationCallback.
+ *
+ */
+ @Test
+ public void CheckCallbackSupport() {
+ String strMsg1 = "In HttpServlet : ServerRuntime CallbackHandler supports CallerPrincipalCallback";
+ String strMsg2 = "In HttpServlet : ServerRuntime CallbackHandler supports GroupPrincipalCallback";
+ String strMsg3 = "In HttpServlet : ServerRuntime CallbackHandler supports PasswordValidationCallback";
+
+ // by invoking this servlet, we are causing code to access our
+ // servlet profile TSServerAuthModule.validateRequest() method
+ // which will perform checks to see which CBH's are supported.
+ responseFromServerWithCredentials(
+ "ModTestServlet" + "?method.under.test=CheckCallbackSupport", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContains(strMsg1, strMsg2, strMsg3));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testGPCIsUserInRole
+ *
+ * @assertion_ids: JASPIC:SPEC:90;
+ * @test_Strategy: The ModTestServlet is called which forces our SAM to invoke
+ * callbacks - including the GPC. This test expects and checks
+ * that the GPC was invoked with non-null principal and that
+ * auth was mandatory and that upon return from
+ * validateRequest, there are values set in
+ * HttpServletRequest.isUserInRole()
+ *
+ * Description This is checking that the group callbacks work
+ * for case of being called with CPC when auth is required and
+ * the check that the validateRequest ensures there was a
+ * return value set for calls to
+ * HttpServletRequest.getRemoteUser()
+ *
+ */
+ @Test
+ public void testGPCIsUserInRole() {
+ String strMsg1 = "In HttpServlet : ServerRuntime GroupPrincipalCallbackSupport():";
+ strMsg1 += " successfully called callbackHandler.handle(callbacks)";
+ strMsg1 += " for servlet: /ModTestServlet";
+ strMsg1 += " with isServletAuthMandatory = " + true;
+
+ // by invoking this servlet, we are causing code to access our
+ // servlet profile TSServerAuthModule.validateRequest() method
+ // which will perform checks to see that GPC is supported and
+ // that the IsUserInRole() is properly populated.
+ String str = readFromServerWithCredentials("ModTestServlet" + "?method.under.test=testGPCIsUserInRole", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+
+ String msg =
+ "testGPCIsUserInRole did not have proper credential values returned in " +
+ "ModTestServlet" + ". this could be due to CBH's not properly doing authentication.";
+
+ assertTrue(msg, str.contains("ModTestServlet->testGPCIsUserInRole() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testGPCGetUserPrincipal
+ *
+ * @assertion_ids: JASPIC:SPEC:90;
+ * @test_Strategy: The ModTestServlet is called which forces our SAM to invoke
+ * callbacks - including the GPC. This test expects and checks
+ * that the GPC was invoked with non-null principal and that
+ * auth was mandatory and that upon return from
+ * validateRequest, there are values set in
+ * HttpServletRequest.getUserPrincipal()
+ *
+ * Description This is checking that the group callbacks work
+ * for case of being called with CPC when auth is required and
+ * the check that the validateRequest ensures there was a
+ * return value set for calls to
+ * HttpServletRequest.getUserPrincipal()
+ *
+ */
+ @Test
+ public void testGPCGetUserPrincipal() {
+
+ String strMsg1 = "In HttpServlet : ServerRuntime GroupPrincipalCallbackSupport():";
+ strMsg1 += " successfully called callbackHandler.handle(callbacks)";
+ strMsg1 += " for servlet: /ModTestServlet";
+ strMsg1 += " with isServletAuthMandatory = " + true;
+
+ // by invoking this servlet, we are causing code to access our
+ // servlet profile TSServerAuthModule.validateRequest() method
+ // which will perform checks to see that GPC is supported and
+ // that the GetUserPrincipal() is properly populated.
+ String str = readFromServerWithCredentials("ModTestServlet" + "?method.under.test=testGPCGetUserPrincipal", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+
+ String msg = "testGPCGetUserPrincipal did not have proper credential values returned in ";
+ msg += "ModTestServlet" + ". this could be due to CBH's not properly doing authentication.";
+
+ assertTrue(msg, str.contains("ModTestServlet->testGPCGetUserPrincipal() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testGPCGetAuthType
+ *
+ * @assertion_ids: JASPIC:SPEC:90;
+ * @test_Strategy: The ModTestServlet is called which forces our SAM to invoke
+ * callbacks - including the GPC. This test expects and checks
+ * that the GPC was invoked with non-null principal and that
+ * auth was mandatory and that upon return from
+ * validateRequest, there are values set in
+ * HttpServletRequest.getAuthType()
+ *
+ * Description This is checking that the group callbacks work
+ * for case of being called with CPC when auth is required and
+ * the check that the validateRequest ensures there was a
+ * return value set for calls to
+ * HttpServletRequest.getAuthType()
+ *
+ */
+ @Test
+ public void testGPCGetAuthType() {
+
+ String strMsg1 = "In HttpServlet : ServerRuntime GroupPrincipalCallbackSupport():";
+ strMsg1 += " successfully called callbackHandler.handle(callbacks)";
+ strMsg1 += " for servlet: /ModTestServlet";
+ strMsg1 += " with isServletAuthMandatory = " + true;
+
+ // by invoking this servlet, we are causing code to access our
+ // servlet profile TSServerAuthModule.validateRequest() method
+ // which will perform checks to see that GPC is supported and
+ // that the GetAuthType() is properly populated.
+ String str = readFromServerWithCredentials("ModTestServlet" + "?method.under.test=testGPCGetAuthType", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+
+ String msg = "testGPCGetAuthType did not have proper credential values returned in ";
+ msg += "ModTestServlet" + ". this could be due to CBH's not properly doing authentication.";
+
+ assertTrue(msg, str.contains("ModTestServlet->testGPCGetAuthType() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckAuthenInValidateRequest
+ *
+ * @assertion_ids: JASPIC:SPEC:90;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify if the validateRequest() was called under the
+ * scenario of already being logged in. If we are already
+ * logged in, then there are (3) HttpServletRequest methods
+ * that must return non-null values:` - getAuthType() -
+ * getRemoteUser() - getUserPrincipal()
+ *
+ * Description The TSSVLog.txt file looking for string that
+ * indicates we found a scenario with only some of the
+ * forementioned methods returned non-null. If a user is
+ * authenticated, they should return non-null values. If the
+ * user is NON authenticated, these methods should return
+ * null.
+ *
+ */
+ @Test
+ public void CheckAuthenInValidateRequest() {
+ String strMsg1 = "validateRequest(): ERROR - invalid authen scenario.";
+ String tempArgs[] = { strMsg1 };
+
+ // by invoking this servlet, we are causing code to access our
+ // servlet profile TSServerAuthModule.validateRequest() method
+ // which will perform checks to see which CBH's are supported.
+ readFromServerWithCredentials("ModTestServlet" + "?method.under.test=CheckAuthenInValidateRequest", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertFalse(logProcessor.verifyLogContains(tempArgs));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testAuthenResultsOnHttpServlet
+ *
+ * @assertion_ids: JASPIC:SPEC:90; JASPIC:SPEC:322;
+ *
+ * @test_Strategy: When authentication is mandatory, after AuthStatus.SUCCESS
+ * is returned from validateRequest, we should be able to
+ * verify that HttpServletRequest has non-null values set for
+ * the following (3) method calls: request.getAuthType()
+ * request.getRemoteUser() request.getUserPrincipal()
+ *
+ * This is based on javadoc for HttpServletRequest as well as
+ * on jsr-196 v1.1 spec section 3.8.1.3 and 3.8.4.
+ *
+ */
+ @Test
+ public void testAuthenResultsOnHttpServlet() {
+ String str = readFromServerWithCredentials("ModTestServlet" + "?method.under.test=testAuthenResultsOnHttpServlet", "j2ee", "j2ee");
+
+ assertTrue(str.contains("ModTestServlet->testAuthenResultsOnHttpServlet() passed"));
+ }
+
+
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testRemoteUserCorrespondsToPrin
+ *
+ * @assertion_ids: JASPIC:SPEC:321;
+ *
+ * @test_Strategy: When authentication is mandatory, after AuthStatus.SUCCESS
+ * is returned from validateRequest, we should be able to
+ * verify that (a) HttpServletRequest has non-null values set
+ * for the following methods: request.getRemoteUser() and
+ * request.getUserPrincipal() (b) that getRemoteUser() and
+ * getUserPrincipal().getName() are equal.
+ *
+ * This is based on javadoc for HttpServletRequest as well as
+ * on jsr-196 v1.1 spec section 3.8.4. Specifically, this is
+ * validating that: "In both cases, the HttpServletRequest
+ * must be modified as necessary to ensure that the Principal
+ * returned by getUserPrincipal and the String returned by
+ * getRemoteUser correspond, ..." Using the above spec
+ * reference COMBINED with the following Servlet spec
+ * reference, we see that:
+ *
+ * (Using Servlet spec v3.1, section 13.3 - it states: "The
+ * getRemoteUser method returns the name of the remote user"
+ * AND "Calling the getName() method on the Principal returned
+ * by getUserPrincipal() returns the name of the remote user."
+ * We can use these two Servlet spec references combined with
+ * our JASPIC reference to validate that principal.getName()
+ * equals (i.e. "corresponds") to the same value returned by
+ * getRemoteUser().
+ *
+ */
+ @Test
+ public void testRemoteUserCorrespondsToPrin() {
+ String str = readFromServerWithCredentials(
+ "ModTestServlet" + "?method.under.test=testRemoteUserCorrespondsToPrin", "j2ee", "j2ee");
+
+ assertTrue(str.contains("ModTestServlet->testRemoteUserCorrespondsToPrin() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testAuthenIsUserInRole
+ *
+ * @assertion_ids: JASPIC:SPEC:321;
+ *
+ * @test_Strategy: When authentication is mandatory, after AuthStatus.SUCCESS
+ * is returned from validateRequest, we should be able to
+ * verify that HttpServletRequest has non-null values set for
+ * the following method call: request.isUserInRole()
+ *
+ * This is based on javadoc for HttpServletRequest as well as
+ * on jsr-196 v1.1 spec section 3.8.1.3 and 3.8.4. There is no
+ * direct spec reference, but it is a scenario that can be
+ * inferred.
+ */
+ @Test
+ public void testAuthenIsUserInRole() {
+ String str = readFromServerWithCredentials(
+ "ModTestServlet" + "?method.under.test=testAuthenIsUserInRole", "j2ee", "j2ee");
+
+ assertTrue(str.contains("ModTestServlet->testAuthenIsUserInRole() passed"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testAuthenAfterLogout
+ *
+ * @assertion_ids: JASPIC:SPEC:98;
+ *
+ * @test_Strategy: When authentication is mandatory, after AuthStatus.SUCCESS
+ * is returned from validateRequest, we should be able to
+ * verify that we can properly login and invoke callback
+ * handlers.
+ *
+ * This test ensures that we can authN when we are not already
+ * pre-logged in. This will call a servlet that is open to
+ * all, (thus no security constraints) and it will invoke the
+ * servlet logout() command. Then it will make a call to a
+ * servlet which requires mandatory authentication. The
+ * premise being that authentication does occur - especially
+ * if not pre-logged in.
+ *
+ * Note the spec does not state that you can not be pre-logged
+ * in but it is saying that authentication has to be able to
+ * succeed in a particular manner. (see spec section 3.8.3.1)
+ *
+ */
+ @Test
+ public void testAuthenAfterLogout() {
+ // call a servlet that is open to all and requires NO authN to access
+ // validate we were not pre-authenticated and if so, force logout
+ String str = readFromServerWithCredentials(allAccessServletPath + "?method.under.test=TestAuthenAfterLogout", "j2ee", "j2ee");
+
+ // now make a call to a servlet that requires mandatory authN and
+ // make sure we still successfully support callbacks
+ str = readFromServerWithCredentials(servletPath + "?method.under.test=testAuthenAfterLogout", "j2ee", "j2ee");
+
+ assertTrue(str.contains("ModTestServlet->testAuthenAfterLogout() passed"));
+
+ // Next make sure we see our CPC being properly called.
+ String strMsg2 = "In HttpServlet : ServerRuntime CallerPrincipalCallback";
+ strMsg2 += " called for profile=HttpServlet for servletPath=" + contextPath + "/" + servletPath;
+ String strMsg3 = "Validated we are not prelogged in for OpenToAllServlet";
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(logProcessor.verifyLogContains(strMsg2, strMsg3));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testGPCWithNoRequiredAuth
+ *
+ * @assertion_ids: JASPIC:SPEC:90;
+ * @test_Strategy: This is checking that the group callbacks work for case of
+ * being called with CPC when no auth is required.
+ *
+ * Description This ultmately calls
+ * ServerCallbackSupport.GroupPrincipalCallbackSupport() with
+ * no required creds.
+ */
+ @Test
+ public void testGPCWithNoRequiredAuth() {
+
+ // By invoking this servlet, we are causing code to access our
+ // servlet profile TSServerAuthModule.validateRequest() method
+ // which will perform checks to see which CBH's are supported.
+ readFromServerWithCredentials(allAccessServletPath + "?method.under.test=testGPCWithNoRequiredAuth", "j2ee", "j2ee");
+
+ String strMsg1 = "In HttpServlet : ServerRuntime GroupPrincipalCallbackSupport():";
+ strMsg1 += " successfully called callbackHandler.handle(callbacks)";
+ strMsg1 += " for servlet: " + "/" + openToAllServletPath;
+ strMsg1 += " with isServletAuthMandatory = " + false;
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: testGPCGetRemoteUser
+ *
+ * @assertion_ids: JASPIC:SPEC:90;
+ * @test_Strategy: The ModTestServlet is called which forces our SAM to invoke
+ * callbacks - including the GPC. This test expects and checks
+ * that the GPC was invoked with non-null principal and that
+ * auth was mandatory and that upon return from
+ * validateRequest, there are values set in
+ * HttpServletRequest.getRemoteUser()
+ *
+ * Description This is checking that the group callbacks work
+ * for case of being called with CPC when auth is required and
+ * the check that the validateRequest ensures there was a
+ * return value set for calls to
+ * HttpServletRequest.getRemoteUser()
+ *
+ */
+ @Test
+ public void testGPCGetRemoteUser() {
+
+ String strChkServlet = "ModTestServlet->testGPCGetRemoteUser() passed";
+
+ String strMsg1 = "In HttpServlet : ServerRuntime GroupPrincipalCallbackSupport():";
+ strMsg1 += " successfully called callbackHandler.handle(callbacks)";
+ strMsg1 += " for servlet: /ModTestServlet";
+ strMsg1 += " with isServletAuthMandatory = " + true;
+
+ // By invoking this servlet, we are causing code to access our
+ // servlet profile TSServerAuthModule.validateRequest() method
+ // which will perform checks to see that GPC is supported and
+ // that the GetRemoteUser() is properly populated.
+ String str = readFromServerWithCredentials(servletPath + "?method.under.test=testGPCGetRemoteUser", "j2ee", "j2ee");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // First, lets make sure CBH's were actually called
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+
+ // Next, lets make sure CBH's set principal values as expected
+ String msg = "testGPCGetRemoteUser did not have proper credential values returned in ";
+ msg += servletPath + ". this could be due to CBH's not properly doing authentication.";
+ assertTrue(msg, str.contains(strChkServlet));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: verifyRuntimeCallOrder
+ *
+ * @assertion_ids: JASPIC:SPEC:317; JASPIC:SPEC:304;
+ *
+ * @test_Strategy: This test verifies that the runtime is invoking the proper
+ * calling order of: validateRequest, process request,
+ * secureResponse.
+ *
+ * Details After AuthStatus.SUCCESS is returned from
+ * validateRequest, we need to verify that the request was
+ * dispatched, and then that the secureResponse() was called -
+ * in that order. We do this by verifying that the messages
+ * (i.e. strMsg1, strMsg2, and strMsg3) were called in the
+ * specific order. The verifyLogContains() method checks these
+ * strings exist within the TSSVLog.txt file AND that they
+ * exist within the log file in order that matches the way
+ * they are declared via "theArgs[]".
+ *
+ */
+ @Test
+ public void verifyRuntimeCallOrder() {
+ // Strings that MUST exist within the authentication-trace-log.xml file
+ String strMsg1 = "TSServerAuthContext.validateRequest called for layer=HttpServlet for requestURI=" + contextPath + "/" + wrapperServletPath;
+ String strMsg2 = "WrapperServlet.doTests() content processed for requestURI";
+ String strMsg3 = "secureResponse called for layer=HttpServlet for requestURI=" + contextPath + "/" + wrapperServletPath;
+
+ invokeServletAndGetResponse(wrapperServletPath, "POST", "testRequestWrapper");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(logProcessor.verifyLogContains(true, strMsg1, strMsg2, strMsg3));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: VerifyClientSubjects
+ *
+ * @assertion_ids: JASPIC:SPEC:96; JASPIC:SPEC:52; JASPIC:JAVADOC:28;
+ * JASPIC:JAVADOC:106; JASPIC:SPEC:23; JASPIC:SPEC:19;
+ * JASPIC:SPEC:51;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to
+ * verify whether the ClientSubject passed to validateRequest
+ * was null or not.
+ *
+ * Description According to spec section 3.8.2: A new
+ * clientSubject must be instantiated and passed in the call
+ * to validateRequest.
+ *
+ */
+ @Test
+ public void VerifyClientSubjects() {
+ String strMsg1 = "HttpServlet profile: ";
+ strMsg1 += "TSServerAuthContext.validateRequest called with non-null client Subject";
+
+ invokeServlet(servletPath, "POST", "VerifyClientSubjects");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // First, verify we have a non-null clientSubject
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+
+ // Now verify we have no occurances of null clientSubjects
+ checkForInvalidClientSubjects(logProcessor);
+
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckMessageInfo
+ *
+ * @assertion_ids: JASPIC:SPEC:95; JASPIC:JAVADOC:28; JASPIC:JAVADOC:10; JASPIC:JAVADOC:11; JASPIC:SPEC:23;
+ * JASPIC:SPEC:19; JASPIC:SPEC:69;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to verify Whether the messageInfo passed to validateRequest()
+ * contains proper values for getRequestMessage() and getResponseMessage().
+ *
+ * Description The MessageInfo argument used in any call made by the message processing runtime to validateRequest must
+ * have been initialized such that the non-null objects returned by the getRequestMessage and getResponseMessage methods
+ * of the MessageInfo are an instanceof HttpServletRequest and HttpServletResponse.
+ *
+ */
+ @Test
+ public void CheckMessageInfo() {
+ String strMsg1 = "validateRequest: MessageInfo.getRequestMessage() is of type ";
+ String strMsg2 = "validateRequest: MessageInfo.getResponseMessage() is of type ";
+
+ // This should work for servlets and static pages
+ // invoking a static should cause the validateRequest to be called
+ invokeServlet(staticPagePath, "POST", "CheckMessageInfo");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(
+ logProcessor.verifyLogContains(
+ strMsg1 + "jakarta.servlet.http.HttpServletRequest",
+ strMsg2 + "jakarta.servlet.http.HttpServletResponse" ));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: VerifyReqPolicy
+ *
+ * @assertion_ids: JASPIC:SPEC:87; JASPIC:JAVADOC:107; JASPIC:JAVADOC:17; JASPIC:JAVADOC:14; JASPIC:JAVADOC:21
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to verify we have more than 1 target policy AND that
+ * ProtectionPolicy.getID() returns a proper value.
+ *
+ *
+ * Description Calling getTargetPolicies on the request MessagePolicy must return an array containing at least one
+ * TargetPolicy whose ProtectionPolicy will be interpreted by the modules of the context to mean that the source of the
+ * corresponding targets within the message is to be authenticated. To that end, calling the getID method on the
+ * ProtectionPolicy must return one of the following values: ProtectionPolicy.AUTHENTICATE_SENDER,
+ * ProtectionPolicy.AUTHENTICATE_CONTENT
+ *
+ */
+ @Test
+ public void VerifyReqPolicy() {
+ invokeServlet(servletPath, "POST", "VerifyReqPolicy");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // First make sure we have an array with more than 1 TargetPolicy
+ checkForInvalidReqPolicy(logProcessor);
+
+ // Next, make sure ProtectionPolicy.getID() returns valid value
+ checkForInvalidProtectionPolicyID(logProcessor);
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: checkSACValidateRequestWithVaryingAccess
+ *
+ * @assertion_ids: JASPIC:SPEC:89; JASPIC:JAVADOC:28
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. read the server side log to verify ServerAuthContext.validateRequest() is called for our
+ * servlet container even when no access will be granted.
+ *
+ * Description This will test that the message processing runtime must call validateRequest independent of whether or
+ * not access to the resource would have been permitted prior to the call to validateRequest. Note: This particular
+ * assertion actually only applies to the case of acceptable connections that have been negotiated and will not be
+ * required for cases where the WebUserDataPermission objects allow a container to determine when to reject a request
+ * befor redirection of that request would ultimately be rejected as a result of an excluding auth-constraint. (an
+ * excluding auth-constraint is an auth-constraint that has no roles. (see JSR-115 spec, section 3.1.3.1, footnote 1)
+ */
+ @Test
+ public void checkSACValidateRequestWithVaryingAccess() {
+ String HDR = "TSServerAuthContext.validateRequest called for layer=HttpServlet";
+ String FTR = " AuthStatus=AuthStatus.SUCCESS";
+ String strMsg1 = HDR + " for requestURI=" + contextPath + "/" + noConstraintPath + FTR;
+ String strMsg2 = HDR + " for requestURI=" + contextPath + "/" + servletPath + FTR;
+
+ // Invoking a servlet should cause the validateRequest to be called
+ // and here we are invoking a url that has no auth-constraints
+ invokeServlet(noConstraintPath, "POST", "checkSACValidateRequestWithVaryingAccess");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+
+ // Invoking a servlet should cause the validateRequest to be called
+ // and here we are invoking a url that has auth-constraints
+ invokeServlet(servletPath, "POST", "checkSACValidateRequestWithVaryingAccess");
+
+ assertTrue(logProcessor.verifyLogContains(strMsg2));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: VerifyMessageInfoObjects
+ *
+ * @assertion_ids: JASPIC:SPEC:60; JASPIC:JAVADOC:27; JASPIC:JAVADOC:28; JASPIC:SPEC:305;
+ *
+ * @test_Strategy:
+ * 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Invoke a servlet to cause a validateRequest invocation, (make sure it is a servlet that has Authen Permissions
+ * enabled so that we can return AuthStatus.SUCCESS from validateRequest() so that we can be sure to enter into
+ * secureResponse(). Once in secureResponse, we want to validate the MessageInfo object is the same as the MessageInfo
+ * object passed into the validateRequest()
+ *
+ * Description Verify that the MessageInfo object passed into the validateRequest() method is the same MessageInfo
+ * object that is passed into secureResponse().
+ *
+ */
+ @Test
+ public void VerifyMessageInfoObjects() {
+ String strMsg1 = "MessageInfo object from secureRequest matches ";
+ strMsg1 += "the messageInfo object from validateRequest";
+
+ // Invoking this servlet should cause the validateRequest and
+ // the secureResponse to be called.
+ invokeServlet(JASPICData.AUTHSTAT_MAND_SUCCESS, "POST", "VerifyMessageInfoObjects");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: VerifyServiceSubjects
+ *
+ * @assertion_ids: JASPIC:SPEC:53; JASPIC:SPEC:61; JASPIC:SPEC:314; JASPIC:SPEC:313; JASPIC:JAVADOC:27;
+ * JASPIC:JAVADOC:28; JASPIC:SPEC:24
+ * @test_Strategy:
+ * 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Invoke a servlet to cause a validateRequest invocation, then read the server side log to
+ * verify we have no valid service subject messages.
+ *
+ * Description Verify that If a non-null Subject was used to acquire the ServerAuthContext, the same Subject must be
+ * passed as the serviceSubject in this call (ie to Point 2 in MPR model).
+ *
+ */
+ @Test
+ public void VerifyServiceSubjects() {
+
+ // Ideally we'd like to find a platform independant way to
+ // also verify that we have valid (non-null) serviceSubjects
+ // but I don't believe this is possible so for now, we will
+ // be content to verify no invalid serviceSubjects were found
+
+ // Invoking a servlet should cause the validateRequest to be called
+ // but does not guarantee a non-null serviceSubject
+ invokeServlet(servletPath, "POST", "VerifyServiceSubjects");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Currently we verify that there were no invalid serviceSubject
+ checkForInvalidServiceSubjects(logProcessor);
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: VerifySAContextVerifyReqIsCalled
+ *
+ * @assertion_ids: JASPIC:SPEC:88; JASPIC:SPEC:50; JASPIC:JAVADOC:28
+ *
+ * @test_Strategy:
+ * 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify ServerAuthContext.validateRequest() is called for our
+ * servlet container.
+ *
+ * Description The inbound processing of requests by a servlet container corresponds to point (2) in the message
+ * processing model. At point (2) in the message processing model, the runtime must call validateRequest on the
+ * ServerAuthContext.
+ *
+ */
+ @Test
+ public void VerifySAContextVerifyReqIsCalled() {
+ // Invoking a servlet should cause the validateRequest to be called
+ invokeServlet(servletPath, "POST", "VerifySAContextVerifyReqIsCalled");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(logProcessor.verifyLogContains("TSServerAuthContext.validateRequest called for layer=HttpServlet"));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckMsgInfoKey
+ *
+ * @assertion_ids: JASPIC:SPEC:306; JASPIC:SPEC:300; JASPIC:JAVADOC:73; JASPIC:SPEC:92; JASPIC:SPEC:24; JASPIC:SPEC:103;
+ *
+ *
+ * @test_Strategy:
+ * 1. invoke servlet that requires authentication
+ * 2. verify that the MesageInfo object passed into getAuthContextID, validateRequest, and secureResponse
+ * all had valid key-value pairs.
+ *
+ * Description: This profile requires that the message processing runtime conditionally establish the following
+ * key-value pair within the Map of the MessageInfo object passed in the calls to getAuthContextID, validateRequest, and
+ * secureResponse. (key) jakarta.security.auth.message.MessagePolicy.isMandatory (val) Any non-null String value, s, for
+ * which Boolean.valueOf(s).booleanValue() == true. The MessageInfo map must contain this key and its associated value,
+ * if and only if authentication is required to perform the resource access corresponding to the HttpServletRequest to
+ * which the ServerAuthContext will be applied.
+ *
+ * If we are Jakarta Authorization compatible, there is an additional test we must make. The key=jakarta.security.jacc.PolicyContext
+ * better exist in the Properties arg passed into getAuthContext().
+ *
+ */
+ @Test
+ public void CheckMsgInfoKey() {
+ String CMN_HDR = "dumpServletProfileKeys() called with attrs: layer=HttpServlet";
+ CMN_HDR += " servletName=/ModTestServlet callerMethod=";
+
+ String CMN_TAIL = " key=jakarta.security.auth.message.MessagePolicy.isMandatory";
+ CMN_TAIL += " value=Valid";
+
+ String strAuthCtxt = CMN_HDR + "getAuthContextID" + CMN_TAIL;
+ String strValReq = CMN_HDR + "validateRequest" + CMN_TAIL;
+
+ // See if we can successfully call into the servlet!
+ invokeServlet(servletPath, "POST", "CheckMsgInfoKey");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(logProcessor.verifyLogContains(strAuthCtxt, strValReq));
+
+ boolean bIs115Compatible = true;
+
+ // ONLY if we are Jakarta Authorization compatible, we want to make an additional key test
+ if (bIs115Compatible) {
+ String HDR = "layer=HttpServlet appContext=" + appContext;
+ String str1 = HDR + " Key=jakarta.security.jacc.PolicyContext does exist thus 115 compatible";
+
+ invokeServlet(servletPath, "POST", "CheckMsgInfoKey");
+
+ // verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContains(str1));
+
+ } else {
+ // Not Jakarta Authorization compatible so the identity must include the caller Principal
+ // (established during the validateRequest processing using the
+ // corresponding CallerPrincipalCallback)
+ //
+ // Note: by testing the subject=non-null, we are actually verifying that
+ // assertion JASPIC:SPEC:103 is met (e.g. non-null clientSubject used in
+ // CallerPrincipalCallback)
+ String strMsg1 = "In HttpServlet : ServerRuntime CallerPrincipalCallback";
+ strMsg1 += " called for profile=HttpServlet for servletPath=" + servletPath;
+ strMsg1 += " subject=non-null principal set = j2ee";
+
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+ }
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckServletAppContext
+ *
+ * @assertion_ids: JASPIC:SPEC:67; JASPIC:SPEC:68; JASPIC:JAVADOC:84; JASPIC:JAVADOC:85;
+ *
+ * @test_Strategy: 1. Verify TSAuthConfigProviderServlet was registered with layer="HttpServlet" and that
+ * TSServerAuthConfig was invoked with this layer value also to satisfy assertion 67.
+ *
+ * 2. Our ProviderConfiguration should have registered a provider for us AND doing that should have caused the MPR to
+ * use the same appContextId for the ACP and ServerAuthConfig. We will check that both were invoked with the
+ * same/expected appContextId to satisfy assertion 68.
+ *
+ * Description: This test will verify that the runtime uses the same appContextId for both the AuthConfigProvider and
+ * the ServerAuthConfig.
+ *
+ */
+ @Test
+ public void CheckServletAppContext() {
+ String acfMsg = "getConfigProvider called for Layer : " + "HttpServlet" + " and AppContext :" + appContext;
+ String sacMsg = "TSServerAuthConfig called for layer=" + "HttpServlet" + " : appContext=" + appContext;
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify TSAuthConfigProviderServlet was registered properly
+ assertTrue(logProcessor.verifyLogContains(acfMsg));
+
+ // Verify runtime used same appContextId for the AuthConfigProvider and ServerAuthConfig
+ assertTrue(logProcessor.verifyLogContains(sacMsg));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckACPConfigObjAppContext
+ *
+ * @assertion_ids: JASPIC:SPEC:74; JASPIC:SPEC:75; JASPIC:SPEC:11; JASPIC:SPEC:13; JASPIC:JAVADOC:94
+ *
+ * @test_Strategy: 1. Verify that a non-null provider was returned during our registration of
+ * TSAuthConfigProviderServlet and that by fact that non-null provider was returned, we need to verify that the MPR
+ * called getServerAuthConfig for that provider. All these verifications need to be done for the corresponding layer and
+ * appContextId values. (this satisfys assertion 75)
+ *
+ * 2. Verify the MPR called getConfigProvider for the layer and appContextId in order to satisfy assertion 74)
+ *
+ * Description: This test will verify that the ACP was properly registered and that the MPR was able to successfully use
+ * getConfigPRovider.
+ *
+ */
+ @Test
+ public void CheckACPConfigObjAppContext() {
+ String sacMsg = "TSAuthConfigProviderServlet.getServerAuthConfig" + " : layer=" + "HttpServlet" + " : appContext=" + appContext;
+
+ // Make sure everything we need is properly setup
+ invokeServlet(servletPath, "POST", "CheckACPConfigObjAppContext");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify non-null provider returned during registration
+ assertTrue(logProcessor.verifyLogContains(ACF_MSG_1));
+
+ // verify MPR called getConfigProvider for the layer and appContextId
+ assertTrue(logProcessor.verifyLogContains(sacMsg));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckACPContextObjAppContext
+ *
+ * @assertion_ids: JASPIC:SPEC:74; JASPIC:SPEC:75; JASPIC:SPEC:77
+ *
+ * @test_Strategy:
+ * 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Read the server side log to verify the following: - verify non-null ACP is returned by ACF
+ * - verify same info used to initialize ACP was also used to initialize the ServerAuthConfig (SAC) for this provider. -
+ * verify same info used in ACP and SAC was also used to init the auth context.
+ *
+ * Description: This test verifies that AuthConfigFactory returns a non-null ACP and that the same info is used to init
+ * the ACP, SAC, and the ServerAuthContext.
+ *
+ */
+ @Test
+ public void CheckACPContextObjAppContext() {
+ String sacMsg = "TSServerAuthConfig called for layer=" + "HttpServlet" + " : appContext=" + appContext;
+ String saConfigMsg = "TSServerAuthContext called for messageLayer=" + "HttpServlet" + " : appContext=" + appContext;
+
+ // Make sure everything we need is properly setup
+ invokeServlet(servletPath, "POST", "CheckACPContextObjAppContext");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // verify non-null ACP is returned by ACF
+ assertTrue(logProcessor.verifyLogContains(ACF_MSG_1));
+
+ // verify same info used to initialize ACP was also used to init SAC
+ assertTrue(logProcessor.verifyLogContains(sacMsg));
+
+ // verify same info used in ACP and SAC was also used to init auth context
+ assertTrue(logProcessor.verifyLogContains(saConfigMsg));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckMPRCallsGetAuthContext
+ *
+ * @assertion_ids: JASPIC:SPEC:74; JASPIC:SPEC:78; JASPIC:JAVADOC:100
+ *
+ * @test_Strategy:
+ * 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify the following: - verify non-null ACP is returned by ACF
+ * - verify ServerAuthConfig.getAuthContext() is called by MPR
+ *
+ * Description: This test is used to test that the MPR properly called ServerAuthConfig.getAuthContext(). This will also
+ * perform an additional test of verifying a non-null ACP is returned by ACF.
+ *
+ */
+ @Test
+ public void CheckMPRCallsGetAuthContext() {
+ String layer = "HttpServlet";
+ String saConfigMsg = "TSServerAuthConfig.getAuthContext: layer=" + layer + " : appContext=" + appContext;
+
+ // Make sure everything we need is properly setup
+ invokeServlet(servletPath, "POST", "CheckMPRCallsGetAuthContext");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Verify non-null ACP is returned by ACF
+ assertTrue(logProcessor.verifyLogContains(ACF_MSG_1));
+
+ // Verify TSServerAuthConfig.getAuthContext() is called by the runtime
+ assertTrue(logProcessor.verifyLogContains(saConfigMsg));
+ }
+
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckforNonNullAuthContext
+ *
+ * @assertion_ids: JASPIC:SPEC:79; JASPIC:JAVADOC:100
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify the following: - verify there were no null values
+ * returned for all calls to getAuthContext() regardless of what operationId is. (this satisfies assertion 79) - verify
+ * we ARE seeing at least one successful value returned from our call to getAuthContext() to satisfy oursleves that the
+ * test really is working correctly as expected.
+ *
+ * Description: This test verifies that there were no null instances of ServerAuthContext objects AND we are also
+ * verifying that we' are getting at least one non-null ServerAuthContext instanace.
+ *
+ */
+ @Test
+ public void CheckforNonNullAuthContext() {
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // This string should NOT/NEVER appear in the log file as
+ // the spec states:
+ // "For all values of the operation argument, the call to
+ // getAuthContext must return a non-null authentication context"
+ assertFalse(logProcessor.verifyLogContains("TSServerAuthConfig.getAuthContext: returned null ServerAuthContext"));
+
+ // We know we should have gotten at least one successful (non-null)
+ // value from our call go getAuthContext so lets check to make sure.
+ assertTrue(logProcessor.verifyLogContains("TSServerAuthConfig.getAuthContext: returned non-null ServerAuthContext"));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: CheckforNonNullCallback
+ *
+ * @assertion_ids: JASPIC:SPEC:71
+ *
+ * @test_Strategy:
+ * 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Read the server side log to verify the following: - verify there was a non-null cbh passed
+ * into the TSAuthConfigProviderServlet.getServerAuthConfig() method. (spec section 3.5 says the cbh must not be null)
+ *
+ * Description: This test verifies that a non-null CakkbackHandler instance passed into the
+ * AuthConfigProvider.getServerAuthConfig().
+ *
+ */
+ @Test
+ public void CheckforNonNullCallback() {
+ String strMsg1 = "layer=HttpServlet appContext=" + appContext;
+ strMsg1 += " getServerAuthConfig() received CallbackHandler=non-null";
+
+ // make sure everything we need is properly setup
+ invokeServlet(servletPath, "POST", "CheckforNonNullCallback");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ assertTrue(logProcessor.verifyLogContains(strMsg1));
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: VerifyNoInvalidEntries
+ *
+ * @assertion_ids: JASPIC:SPEC:52; JASPIC:SPEC:96; JASPIC:SPEC:53; JASPIC:SPEC:87; JASPIC:SPEC:313; JASPIC:SPEC:60;
+ * JASPIC:JAVADOC:106; JASPIC:SPEC:322; JASPIC:SPEC:323;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Invoke a series of web pages with varying servlet perms and access/connection scenarios.
+ *
+ * 3. Use FetchLog servlet to read the server side log to verify no invalid scenarios were encountered.
+ *
+ *
+ * Description This is a negative test case that is used to assist in verifying several different assertions. The
+ * intention of this test is to make sure accessing web resources under different circumstances should NOT cause any
+ * invalid issues to be encountered.
+ *
+ */
+ @Test
+ public void VerifyNoInvalidEntries() {
+ // Try to invoke different servlet pages to see if this
+ // causes an invalid condition to occur
+ invokeServlet(staticPagePath, "POST", "VerifyNoInvalidEntries");
+ invokeServlet(noConstraintPath, "POST", "VerifyNoInvalidEntries");
+ invokeServlet(servletPath, "POST", "VerifyNoInvalidEntries");
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ logProcessor.fetchLogs();
+
+ // Now check log file looking for invalid entries
+ doCommonVerificationChecks(logProcessor);
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFSwitchFactorys
+ *
+ * @assertion_ids:
+ *
+ *
+ * @test_Strategy: This test does the following: - gets current (CTS) factory - sets the vendors ACF thus replacing the
+ * CTS ACF - verify ACF's were correctly set - reset factory back to the original CTS factory
+ *
+ * 1. Use the static setFactory method to set an ACF and this should always work. and use the getFactory to verify it
+ * worked.
+ *
+ * Description
+ *
+ */
+ @Test
+ public void ACFSwitchFactorys() {
+ String strMsg1 = "ACFTestServlet->ACFSwitchFactorys() passed";
+
+ String str = invokeServletAndGetResponse(acfServletPath, "POST", "ACFSwitchFactorys");
+
+ assertTrue(str.contains(strMsg1));
+ }
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: ACFRemoveRegistrationWithBadId
+ *
+ * @assertion_ids: JASPIC:SPEC:345;
+ *
+ *
+ * @test_Strategy: This test verifies we get a return value of False when invoking ACF.removeRegistration(some_bad_id);
+ *
+ * 1. Use the static setFactory method to get an ACF and then attempt to invoke removeRegistration() with an invalid (ie
+ * non-existant) regId. This should return False (per javadoc).
+ *
+ * Description
+ *
+ */
+ @Test
+ public void ACFRemoveRegistrationWithBadId() {
+ String strMsg1 = "ACFTestServlet->ACFRemoveRegistrationWithBadId() passed";
+
+ String str = invokeServletAndGetResponse(acfServletPath, "POST", "ACFRemoveRegistrationWithBadId");
+
+ assertTrue(str.contains(strMsg1));
+ }
+
+ /**
+ * This is convenience method that can be called anywhere and is intended to be used to make sure no unwanted log
+ * messages appear which would indicate a failure.
+ *
+ *
+ * To clarify, this means that a particular test case ~may~ cause some
+ * unexpected error to occur which would result in a log message getting dumped to the log file - even though we may not
+ * be testing that particular assertion at that given moment. This method can be used as a final pass at the end of each
+ * test to ensure that no accidental/unexpected errors were encountered.
+ *
+ */
+ private void doCommonVerificationChecks(LogFileProcessor logProcessor) {
+ // Checks that should ALWAYS pass
+ checkForInvalidReqPolicy(logProcessor);
+ checkForInvalidProtectionPolicyID(logProcessor);
+ checkForInvalidServiceSubjects(logProcessor);
+ checkForInvalidClientSubjects(logProcessor);
+ checkForInvalidMessageInfoObjs(logProcessor);
+ checkForNullCallback(logProcessor);
+ checkForNullAuthConfigObj(logProcessor);
+ checkForAuthenMisMatch(logProcessor);
+ checkForinvalidMsgInfoMapKey(logProcessor);
+ }
+
+ /**
+ * This is used to verify assertion JASPIC:SPEC:52 and JASPIC:SPEC:96 which
+ * states that A new clientSubject must be instantiated and passed in the call
+ * to validateRequest. (see spec section 3.8.2) We look for occurances of
+ * strings that indicate we have a null clientSubject passed into our
+ * validateRequest and we issue a failure if a match is found.
+ */
+ private void checkForInvalidClientSubjects(LogFileProcessor logProcessor) {
+ String strMsg2 = "FAILURE detected - ClientSubjects should not be read-only.";
+ String strMsg3 = "FAILURE detected - ClientSubjects should not be null.";
+ String strMsg1 = "HttpServlet profile: ";
+ strMsg1 += "TSServerAuthContext.validateRequest called with null client Subject";
+ String tempArgs1[] = { strMsg1, strMsg2, strMsg3 };
+
+ assertFalse(logProcessor.verifyLogContainsOneOf(tempArgs1));
+ }
+
+ /**
+ * This is convenience method that helps verify assertion JASPIC:SPEC:87 which states that for the Servlet profile,
+ * Calling getTargetPolicies on the request MessagePolicy must return an array containing at least one TargetPolicy. We
+ * look for a message that will be printed out if any calls to getTargetPolicies return an array with less than one
+ * TargetPolicy.
+ *
+ */
+ private void checkForInvalidReqPolicy(LogFileProcessor logProcessor) {
+ String strMsg1 = "Layer=HttpServlet requestPolicy=invalid";
+ strMsg1 += " in TSServerAuthModule.initialize()";
+ String tempArgs[] = { strMsg1 };
+
+ assertFalse(logProcessor.verifyLogContainsOneOf(tempArgs));
+ }
+
+ /**
+ * This is convenience method that helps verify assertion JASPIC:SPEC:87 which states that for the Servlet profile,
+ * Calling the getID() method on the ProtectionPolicy must return a valid ID type (as defined in spec section 3.7.4). We
+ * look for a message that will be printed out if any calls to getID() returned an invalid ProtectionPolicy ID.
+ *
+ */
+ private void checkForInvalidProtectionPolicyID(LogFileProcessor logProcessor) {
+ String strMsg1 = "Layer=HttpServlet Invalid ProtectionPolicy.getID()";
+ String tempArgs[] = { strMsg1 };
+
+ assertFalse(logProcessor.verifyLogContainsOneOf(tempArgs));
+ }
+
+ /**
+ * This is convenience method that helps verify assertions related to the validateRequest and secureResponse methods.
+ * This tests assertion JASPIC:SPEC:53 which states that for the Servlet profile, If a non-null Subject was used to
+ * acquire the ServerAuthContext, the same Subject must be passed as the serviceSubject in this call.
+ *
+ * This also tests assertion JASPIC:SPEC:313 which states that along with the above requirments if a non-null
+ * serviceSubject is used in this call, it must not be read-only. (see spec section 2.1.5.2).
+ *
+ * Also tested are assertions JASPIC:SPEC:61, JASPIC:SPEC:314 and JASPIC:SPEC:313.
+ *
+ * We look for occurances of strings that indicate we have a serviceSubject mismatch in our runtime - which we should
+ * not have.
+ */
+ private void checkForInvalidServiceSubjects(LogFileProcessor logProcessor) {
+ String strMsg1 = "FAILURE detected - ServiceSubjects should be the same and are not.";
+ String strMsg5 = "FAILURE detected - SecureResponse ServiceSubjects should be the same and are not.";
+ String strMsg6 = "FAILURE detected - SecureResponse ServiceSubjects should not be read-only.";
+ String tempArgs1[] = { strMsg1 };
+ String tempArgs5[] = { strMsg5 }; // assertion: JASPIC:SPEC:61 and JASPIC:SPEC:314
+ String tempArgs6[] = { strMsg6 }; // assertion: JASPIC:SPEC:313
+
+ String strMsg2 = "ServiceSubjects correctly matched.";
+ String strMsg3 = "found a non-null serviceSubject in getAuthContext()";
+ String strMsg4 = "FAILURE detected - ServiceSubjects should not be read-only.";
+
+ assertFalse(logProcessor.verifyLogContainsOneOf(tempArgs1));
+ assertFalse(logProcessor.verifyLogContainsOneOf(tempArgs5));
+ assertFalse(logProcessor.verifyLogContainsOneOf(tempArgs6));
+
+ if (logProcessor.verifyLogContains(strMsg3)) {
+
+ // We know that there was a non-null subject passed into getAuthContext()
+ // so we better find strMsg2 in our log file too!
+ assertTrue(logProcessor.verifyLogContains(strMsg2));
+
+ // If we made it to here, then we have matching serviceSubjects
+ // and we should NOT have a read-only service subject
+ assertFalse(logProcessor.verifyLogContains(strMsg4));
+ }
+ }
+
+ /**
+ * This is used to verify assertion JASPIC:SPEC:323 which states in spec section 3.8.4 (para 2)
+ *
+ */
+ private void checkForinvalidMsgInfoMapKey(LogFileProcessor logProcessor) {
+ String strMsg1 = "ERROR - invalid setting for jakarta.servlet.http.authType = null";
+ String strMsg2 = "ERROR - mismatch value set for jakarta.servlet.http.authType and getAuthType()";
+ String tempArgs1[] = { strMsg1, strMsg2 };
+
+ // verify that we had NO mismatches between getAuthType() and
+ // getRemoteUser()
+ assertFalse(logProcessor.verifyLogContainsOneOf(tempArgs1));
+ }
+
+ /**
+ * This is used to verify assertion JASPIC:SPEC:322 which states in spec section 3.8.4 (para 1) "Both cases, must also
+ * ensure that the value returned by calling getAuthType on the HttpServletRequest is consistent in terms of being null
+ * or non-null with the value returned by getUserPrincipal."
+ *
+ */
+ private void checkForAuthenMisMatch(LogFileProcessor logProcessor) {
+ String strMsg1 = "ERROR - HttpServletRequest authentication result mis-match with getAuthType() and getRemoteUser()";
+
+ // Verify that we had NO mismatches between getAuthType() and
+ // getRemoteUser()
+ assertFalse(logProcessor.verifyLogContains(strMsg1));
+ }
+
+ /**
+ * This is used to verify assertion JASPIC:SPEC:16 which states that the AuthConfigProvider must NOT return a null auth
+ * config object (in the getServerAuthConfig() call)
+ */
+ private void checkForNullAuthConfigObj(LogFileProcessor logProcessor) {
+ String strMsg1 = "WARNING: getServerAuthConfig() returned null";
+
+ // verify that we had NO bad callbacks passed in
+ assertFalse(logProcessor.verifyLogContains(strMsg1));
+ }
+
+ /**
+ * This is used to verify assertion JASPIC:SPEC:71 which states that the cbh passed into
+ * AuthConfigProvider.getServerAuthConfig() must NOT be null. (see spec section 3.5)
+ */
+ private void checkForNullCallback(LogFileProcessor logProcessor) {
+ String strMsg1 = "FAILURE: layer=HttpServlet appContext=" + appContext;
+ strMsg1 += " getServerAuthConfig() received CallbackHandler=null";
+
+ // verify that we had NO bad callbacks passed in
+ assertFalse(logProcessor.verifyLogContains(strMsg1));
+ }
+
+ /**
+ * This is used to verify assertion JASPIC:SPEC:60 which states that the runtime must pass the same MessageInfo instance
+ * (that was passed to validateRequest) into secureRequest. (see spec section 2.1.5.2)
+ */
+ private void checkForInvalidMessageInfoObjs(LogFileProcessor logProcessor) {
+ String strMsg1 = "FAILURE: MessageInfo object in secureRequest does not";
+ strMsg1 += " match the messageInfo object from validateRequest";
+
+ assertFalse(logProcessor.verifyLogContains(strMsg1));
+
+ }
+
+
+ private void invokeServlet(String path, String method, String test) {
+ readFromServerWithCredentials(path + "?method.under.test=test", "j2ee", "j2ee");
+ }
+
+ private String invokeServletAndGetResponse(String path, String method, String test) {
+ return readFromServerWithCredentials(path + "?method.under.test=" + test, "j2ee", "j2ee");
+ }
+
+
+}
\ No newline at end of file
diff --git a/tck/spi/servlet/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletUnitTest.java b/tck/spi/servlet/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletUnitTest.java
new file mode 100644
index 0000000..620f7c7
--- /dev/null
+++ b/tck/spi/servlet/src/test/java/ee/jakarta/tck/authentication/test/basic/ServletUnitTest.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2022-2022 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package ee.jakarta.tck.authentication.test.basic;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationEntry;
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationXMLFileProcessor;
+import ee.jakarta.tck.authentication.test.basic.sam.TSAuthConfigProviderServlet;
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigFactoryForStandalone;
+import ee.jakarta.tck.authentication.test.basic.servlet.IdUtil;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.AuthConfigProvider;
+import java.util.Collection;
+import java.util.logging.Logger;
+import org.junit.Test;
+
+/**
+ * A small collection of unit tests for testing the AuthConfigFactory.
+ *
+ *
+ * This only uses code directly in the test context, and does not start up a server.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class ServletUnitTest {
+
+ Logger logger = Logger.getLogger(ServletUnitTest.class.getName());
+
+ /**
+ *
+ * @keywords: jaspic_servlet
+ *
+ * @testName: AuthConfigFactorySetFactory
+ *
+ * @assertion_ids: JASPIC:SPEC:7; JASPIC:SPEC:10; JASPIC:JAVADOC:87; JASPIC:JAVADOC:80
+ *
+ * @test_Strategy: 1. Use the static setFactory method to set an ACF and this should always work.
+ *
+ * Description This method uses the getFactory() method to get the current factory, then it uses the setFactory() to
+ * change the current ACF. This method then verifies that the ACF's were indeed changed. We know that the setFactory()
+ * works as it is used in the bootstrap process - but this is an additional level of testing that allows us to set the
+ * factory in a slightly different manner than the bootstrap (eg reading it out of the java.security file.
+ */
+ @Test
+ public void AuthConfigFactorySetFactory() {
+
+ try {
+ // Set our AuthConfigFactory to a new/different AuthConfigFactory
+ TSAuthConfigFactoryForStandalone newAuthConfigFactory = new TSAuthConfigFactoryForStandalone();
+ AuthConfigFactory.setFactory(newAuthConfigFactory);
+ String newAuthConfigFactoryClass = newAuthConfigFactory.getClass().getName();
+
+ // Verify our calls to getFactory() are getting the newly set factory
+ // instance and not the original ACF instance
+ AuthConfigFactory testAuthConfigFactory = AuthConfigFactory.getFactory();
+ assertNotNull(testAuthConfigFactory);
+
+ String newlySetACFClass = testAuthConfigFactory.getClass().getName();
+
+ assertEquals("FAILURE - our current ACF does not match our newly set ACF",newlySetACFClass, newAuthConfigFactoryClass);
+
+ } catch (SecurityException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: getRegistrationContextId
+ *
+ * @assertion_ids: JASPIC:JAVADOC:77
+ *
+ * @test_Strategy: 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Use the system properties to read the TestSuite providers defined in ProviderConfigruation.xml file and register
+ * them with vendor's authconfig factory.
+ *
+ *
+ * Description This will use an appContext value that was used to register a provider, and it will see if it can use the
+ * AuthConfigFactory.RegistrationContext API to try and access the same appContext value that was used during the
+ * registration process.
+ *
+ */
+ @Test
+ public void getRegistrationContextId() {
+ String appContext = System.getProperty("logical.hostname.servlet") + " /spitests_servlet_web";
+
+ // register providers in vendor factory
+ assertTrue(register(
+ System.getProperty("log.file.location"),
+ System.getProperty("provider.configuration.file"),
+ System.getProperty("vendor.authconfig.factory")));
+
+ // verify we can access a given provider (any provider) appcontext id
+ boolean bVerified = false;
+
+ AuthConfigFactory authConfigFactory = null;
+
+ try {
+ authConfigFactory = AuthConfigFactory.getFactory();
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory.";
+ msg = msg + " Check your server side security policies.";
+ logger.info(msg);
+ ex.printStackTrace();
+ }
+
+ assertNotNull(
+ "getRegistrationContextId(): Error - call to getFactory() returned null ACF.",
+ authConfigFactory);
+
+ String[] regIDs = authConfigFactory.getRegistrationIDs(null);
+ for (int ii = 0; ii < regIDs.length; ii++) {
+ // loop through the AuthConfigFactory's registration ids
+
+ if (regIDs[ii] != null) {
+ AuthConfigFactory.RegistrationContext acfReg;
+ acfReg = authConfigFactory.getRegistrationContext(regIDs[ii]);
+ if (acfReg != null) {
+ logger.info("appContext = " + appContext);
+ logger.info("acfReg.getAppContext() = " + acfReg.getAppContext());
+ logger.info("layer = " + acfReg.getMessageLayer());
+ String str = acfReg.getAppContext();
+ if ((str != null) && (str.equals(appContext))) {
+ // We found our provider info
+ logger.info("Found it : RegistrationID for our ACP=" + regIDs[ii]);
+ bVerified = true;
+ break;
+ }
+ }
+ }
+ }
+
+ assertTrue(
+ "Could not find appContext=" + appContext + " in the ACF's list of registration id info",
+ bVerified);
+ }
+
+ /**
+ * @keywords: jaspic_servlet
+ *
+ * @testName: AuthConfigFactoryVerifyPersistence
+ *
+ * @assertion_ids: JASPIC:JAVADOC:75
+ *
+ * @test_Strategy: 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Load vendor's AuthConfigFactory and make sure the registered providers return properly for the right message layer
+ * and appContextId
+ *
+ * Note: We test the persistance behaviour for vendor's AuthConfigFactory by registering providers from a persisted
+ * file, then we verify the registrations went correctly.
+ *
+ * Description
+ *
+ *
+ */
+ @Test
+ public void AuthConfigFactoryVerifyPersistence() {
+ boolean verified = false;
+
+ try {
+ // Register providers in vendor factory
+ assertTrue(register(
+ System.getProperty("log.file.location"),
+ System.getProperty("provider.configuration.file"),
+ System.getProperty("vendor.authconfig.factory")));
+
+ // Get system default AuthConfigFactory
+ AuthConfigFactory acf = AuthConfigFactory.getFactory();
+
+ if (acf != null) {
+ logger.info("Default AuthConfigFactory class name = " + acf.getClass().getName());
+
+ verified = verifyRegistrations(acf);
+
+ } else {
+ logger.info("Default AuthConfigFactory is null" + " can't verify registrations for TestSuite Providers");
+ }
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory.";
+ msg = msg + " Check your server side security policies.";
+ logger.info(msg);
+ ex.printStackTrace();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ assertTrue(
+ "AuthConfigFactoryPersistence failed",
+ verified);
+ }
+
+ private boolean register(String logFileLocation, String providerConfigurationFileLocation, String vendorAuthConfigFactoryClass) {
+ try {
+ printVerticalIndent();
+
+ // Get an instance of Vendor's AuthConfigFactory
+ AuthConfigFactory vendorFactory = getAuthConfigFactory(vendorAuthConfigFactoryClass);
+
+ // Set vendor's AuthConfigFactory
+ AuthConfigFactory.setFactory(vendorFactory);
+
+ // Get system default AuthConfigFactory (which we just set to vendor)
+ AuthConfigFactory authConfigFactory = AuthConfigFactory.getFactory();
+
+ if (authConfigFactory != null) {
+ logger.info("Default AuthConfigFactory class name = " + authConfigFactory.getClass().getName());
+
+ } else {
+ logger.info("Default AuthConfigFactory is null" + " can't register TestSuite Providers with null");
+ return false;
+ }
+
+ /**
+ * Read the ProviderConfiguration XML file This file contains the list of providers that needs to be loaded by the
+ * vendor's default AuthConfigFactory
+ */
+ Collection providerConfigurationEntries =
+ readProviderConfigurationXMLFile(providerConfigurationFileLocation);
+
+
+ printVerticalIndent();
+
+ for (ProviderConfigurationEntry providerConfigurationEntry : providerConfigurationEntries) {
+ // Obtain each ProviderConfigurationEntry and register it with vendor's default AuthConfigFactory
+
+ if (providerConfigurationEntry != null) {
+ logger.info("Registering Provider " + providerConfigurationEntry.getProviderClassName() + " ...");
+ authConfigFactory.registerConfigProvider(
+ providerConfigurationEntry.getProviderClassName(),
+ providerConfigurationEntry.getProperties(),
+ providerConfigurationEntry.getMessageLayer(),
+ providerConfigurationEntry.getApplicationContextId(),
+ providerConfigurationEntry.getRegistrationDescription());
+ logger.info("Registration Successful");
+ }
+ }
+
+ printVerticalIndent();
+
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory";
+ msg = msg + "or ACF.setFactory(). Check your server side security policies.";
+ logger.info(msg);
+ ex.printStackTrace();
+
+ } catch (Exception e) {
+ logger.info("Error Registering TestSuite AuthConfig Providers");
+ e.printStackTrace();
+ }
+
+ return true;
+
+ }
+
+ /**
+ * This method instantiates and ruturns a AuthConfigFactory based on the specified className
+ */
+ private AuthConfigFactory getAuthConfigFactory(String className) {
+ AuthConfigFactory authConfigFactory = null;
+
+ if (className != null) {
+ try {
+ authConfigFactory = (AuthConfigFactory)
+ Class.forName(className, true, Thread.currentThread().getContextClassLoader())
+ .getDeclaredConstructor()
+ .newInstance();
+ logger.info("Instantiated AuthConfigFactory for: " + className);
+
+ } catch (Exception e) {
+ logger.info("Error instantiating vendor's " + "AuthConfigFactory class :" + className);
+ e.printStackTrace();
+
+ }
+ }
+
+ return authConfigFactory;
+ }
+
+ /*
+ * Read the provider configuration XML file and registers each provider with Vendor's default AuthConfigFactory
+ */
+ private Collection readProviderConfigurationXMLFile(String providerConfigurationFileLocation) {
+ Collection providerConfigurationEntriesCollection = null;
+
+ logger.info("Reading TestSuite Providers from :" + providerConfigurationFileLocation);
+ try {
+ // Given the provider configuration xml file
+ // This reader parses the xml file and stores the configuration
+ // entries as a collection.
+ ProviderConfigurationXMLFileProcessor configFileProcessor =
+ new ProviderConfigurationXMLFileProcessor(providerConfigurationFileLocation);
+
+ // Retrieve the ProviderConfigurationEntries collection
+ providerConfigurationEntriesCollection = configFileProcessor.getProviderConfigurationEntriesCollection();
+
+ logger.info("TestSuite Providers read successfully " + "from ProviderConfiguration.xml file");
+
+ return providerConfigurationEntriesCollection;
+
+ } catch (Exception e) {
+ logger.info("Error loading Providers");
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private boolean verifyRegistrations(AuthConfigFactory authConfigFactory) {
+ logger.info("Verifying Provider Registrations ...");
+
+ String servletAppContext = IdUtil.getAppContextId(JASPICData.LAYER_SERVLET);
+
+ try {
+ // Get AuthConfigProviderServlet
+ AuthConfigProvider servletAuthConfigProvider =
+ authConfigFactory.getConfigProvider(JASPICData.LAYER_SERVLET, servletAppContext, null);
+
+ if (servletAuthConfigProvider != null) {
+ if (servletAuthConfigProvider.getClass().getName().equals(TSAuthConfigProviderServlet.class.getName())) {
+ logger.info("TSAuthConfigProviderServlet registered for" + " message layer=HttpServlet" + " and appContextId="
+ + servletAppContext);
+ } else {
+ logger.info("Wrong provider registerd for " + " message layer=HttpServlet" + " and appContextId=" + servletAppContext);
+ return false;
+ }
+
+ } else {
+ logger.info("Error : No AuthConfigprovider registerd for" + " message layer=HttpServlet" + " and appContextId="
+ + servletAppContext);
+ return false;
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return true;
+ }
+
+ private void printVerticalIndent() {
+ logger.info("**********************************************************");
+ logger.info("\n");
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/tck/spi/soap/auth.conf b/tck/spi/soap/auth.conf
new file mode 100644
index 0000000..6733343
--- /dev/null
+++ b/tck/spi/soap/auth.conf
@@ -0,0 +1,34 @@
+reg-entry {
+ con-entry {
+ ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigProvider
+ AuthStatus_SEND_SUCCESS:false
+ requestPolicy:USER_NAME_PASSWORD
+ }
+ reg-ctx {
+ layer:SOAP
+ app-ctx:null
+ description:TestSuite JSR 196 Config Provider
+ }
+ reg-ctx {
+ layer:SOAP
+ app-ctx:localhost /Hello_web/Hello
+ description:TestSuite JSR 196 Config Provider
+ }
+}
+reg-entry {
+ con-entry {
+ ee.jakarta.tck.authentication.test.basic.sam.TSAuthConfigProviderServlet
+ AuthStatus_SEND_SUCCESS:true
+ requestPolicy:USER_NAME_PASSWORD
+ }
+ reg-ctx {
+ layer:HttpServlet
+ app-ctx:server /spitests_servlet_web
+ description:Registration for TSAuthConfigProviderServlet using spitests_servlet_web
+ }
+ reg-ctx {
+ layer:HttpServlet
+ app-ctx:server /spitests_servlet_web/WrapperServlet
+ description:Registration for TSAuthConfigProviderServlet using spitests_servlet_web
+ }
+}
diff --git a/tck/spi/soap/pom.xml b/tck/spi/soap/pom.xml
new file mode 100644
index 0000000..6e78bb0
--- /dev/null
+++ b/tck/spi/soap/pom.xml
@@ -0,0 +1,154 @@
+
+
+
+ 4.0.0
+
+
+ org.eclipse.ee4j.tck.authentication
+ jakarta-authentication-tck
+ 3.1.0-SNAPSHOT
+
+
+ spi.soap
+ war
+
+ Jakarta Authentication TCK - Profile SPI SOAP
+
+ A lot of tests about the nitty gritty regarding the SPI per profile.
+
+
+
+
+ org.jakartaee
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+ org.eclipse.ee4j.tck.authentication
+ spi.common
+ ${project.version}
+
+
+
+ jakarta.jws
+ jakarta.jws-api
+ 3.0.0
+
+
+ org.glassfish.metro
+ webservices-rt
+ 4.0.3
+
+
+ org.glassfish.main.security
+ webservices.security
+ 8.0.0-SNAPSHOT
+
+
+ jakarta.xml.ws
+ jakarta.xml.ws-api
+ 4.0.2
+
+
+ jakarta.xml.soap
+ jakarta.xml.soap-api
+ 3.0.2
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ 4.0.2
+
+
+
+
+ spitests_servlet_web
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+
+ org.apache.maven.plugins
+
+
+ maven-dependency-plugin
+
+
+ [3.2.0,)
+
+
+ unpack
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ com.sun.xml.ws
+ jaxws-maven-plugin
+ 4.0.2
+
+
+
+ generate-sources
+
+
+ wsimport
+
+
+ ee.jakarta.tck.authentication.test.basic.soap
+
+
+
+ ${basedir}/src/main/webapp/WEB-INF/HelloService.wsdl
+
+
+ http://localhost:8080/spitests_servlet_web/HelloService?wsdl
+
+ true
+ ${basedir}/src/main/java
+ 3.0
+
+
+
+
+
+
+
diff --git a/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/AuthFactoryContainerInitializer.java b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/AuthFactoryContainerInitializer.java
new file mode 100644
index 0000000..61f6593
--- /dev/null
+++ b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/AuthFactoryContainerInitializer.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigFactory;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.servlet.ServletContainerInitializer;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import java.util.Set;
+
+public class AuthFactoryContainerInitializer implements ServletContainerInitializer {
+
+ @Override
+ public void onStartup(Set> c, ServletContext ctx) throws ServletException {
+ AuthConfigFactory.setFactory(new TSAuthConfigFactory());
+ }
+
+}
diff --git a/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/Hello.java b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/Hello.java
new file mode 100644
index 0000000..833e58f
--- /dev/null
+++ b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/Hello.java
@@ -0,0 +1,42 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import jakarta.jws.WebMethod;
+import jakarta.jws.WebParam;
+import jakarta.jws.WebResult;
+import jakarta.jws.WebService;
+import jakarta.xml.bind.annotation.XmlSeeAlso;
+import jakarta.xml.ws.Action;
+import jakarta.xml.ws.RequestWrapper;
+import jakarta.xml.ws.ResponseWrapper;
+
+
+/**
+ * This class was generated by the XML-WS Tools.
+ * XML-WS Tools 4.0.1
+ * Generated source version: 3.0
+ *
+ */
+@WebService(name = "Hello", targetNamespace = "http://soap.basic.test.authentication.tck.jakarta.ee/")
+@XmlSeeAlso({
+ ObjectFactory.class
+})
+public interface Hello {
+
+
+ /**
+ *
+ * @param arg0
+ * @return
+ * returns java.lang.String
+ */
+ @WebMethod
+ @WebResult(targetNamespace = "")
+ @RequestWrapper(localName = "sayHelloProtected", targetNamespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", className = "ee.jakarta.tck.authentication.test.basic.soap.SayHelloProtected")
+ @ResponseWrapper(localName = "sayHelloProtectedResponse", targetNamespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", className = "ee.jakarta.tck.authentication.test.basic.soap.SayHelloProtectedResponse")
+ @Action(input = "http://soap.basic.test.authentication.tck.jakarta.ee/Hello/sayHelloProtectedRequest", output = "http://soap.basic.test.authentication.tck.jakarta.ee/Hello/sayHelloProtectedResponse")
+ public String sayHelloProtected(
+ @WebParam(name = "arg0", targetNamespace = "")
+ String arg0);
+
+}
diff --git a/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/HelloImpl.java b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/HelloImpl.java
new file mode 100644
index 0000000..cb82bc6
--- /dev/null
+++ b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/HelloImpl.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007, 2020 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import jakarta.jws.WebMethod;
+import jakarta.jws.WebService;
+
+@WebService(name = "Hello", serviceName = "HelloService")
+public class HelloImpl {
+
+ @WebMethod
+ public String sayHelloProtected(String param) {
+ return "Hello " + param;
+ }
+}
diff --git a/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/HelloService.java b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/HelloService.java
new file mode 100644
index 0000000..311f85a
--- /dev/null
+++ b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/HelloService.java
@@ -0,0 +1,94 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import javax.xml.namespace.QName;
+import jakarta.xml.ws.Service;
+import jakarta.xml.ws.WebEndpoint;
+import jakarta.xml.ws.WebServiceClient;
+import jakarta.xml.ws.WebServiceException;
+import jakarta.xml.ws.WebServiceFeature;
+
+
+/**
+ * This class was generated by the XML-WS Tools.
+ * XML-WS Tools 4.0.1
+ * Generated source version: 3.0
+ *
+ */
+@WebServiceClient(name = "HelloService", targetNamespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", wsdlLocation = "http://localhost:8080/spitests_servlet_web/HelloService?wsdl")
+public class HelloService
+ extends Service
+{
+
+ private static final URL HELLOSERVICE_WSDL_LOCATION;
+ private static final WebServiceException HELLOSERVICE_EXCEPTION;
+ private static final QName HELLOSERVICE_QNAME = new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloService");
+
+ static {
+ URL url = null;
+ WebServiceException e = null;
+ try {
+ url = new URL("http://localhost:8080/spitests_servlet_web/HelloService?wsdl");
+ } catch (MalformedURLException ex) {
+ e = new WebServiceException(ex);
+ }
+ HELLOSERVICE_WSDL_LOCATION = url;
+ HELLOSERVICE_EXCEPTION = e;
+ }
+
+ public HelloService() {
+ super(__getWsdlLocation(), HELLOSERVICE_QNAME);
+ }
+
+ public HelloService(WebServiceFeature... features) {
+ super(__getWsdlLocation(), HELLOSERVICE_QNAME, features);
+ }
+
+ public HelloService(URL wsdlLocation) {
+ super(wsdlLocation, HELLOSERVICE_QNAME);
+ }
+
+ public HelloService(URL wsdlLocation, WebServiceFeature... features) {
+ super(wsdlLocation, HELLOSERVICE_QNAME, features);
+ }
+
+ public HelloService(URL wsdlLocation, QName serviceName) {
+ super(wsdlLocation, serviceName);
+ }
+
+ public HelloService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
+ super(wsdlLocation, serviceName, features);
+ }
+
+ /**
+ *
+ * @return
+ * returns Hello
+ */
+ @WebEndpoint(name = "HelloPort")
+ public Hello getHelloPort() {
+ return super.getPort(new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloPort"), Hello.class);
+ }
+
+ /**
+ *
+ * @param features
+ * A list of {@link jakarta.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features parameter will have their default values.
+ * @return
+ * returns Hello
+ */
+ @WebEndpoint(name = "HelloPort")
+ public Hello getHelloPort(WebServiceFeature... features) {
+ return super.getPort(new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloPort"), Hello.class, features);
+ }
+
+ private static URL __getWsdlLocation() {
+ if (HELLOSERVICE_EXCEPTION!= null) {
+ throw HELLOSERVICE_EXCEPTION;
+ }
+ return HELLOSERVICE_WSDL_LOCATION;
+ }
+
+}
diff --git a/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/ObjectFactory.java b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/ObjectFactory.java
new file mode 100644
index 0000000..2c49164
--- /dev/null
+++ b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/ObjectFactory.java
@@ -0,0 +1,83 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import javax.xml.namespace.QName;
+import jakarta.xml.bind.JAXBElement;
+import jakarta.xml.bind.annotation.XmlElementDecl;
+import jakarta.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the ee.jakarta.tck.authentication.test.basic.soap package.
+ *
An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private static final QName _SayHelloProtected_QNAME = new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "sayHelloProtected");
+ private static final QName _SayHelloProtectedResponse_QNAME = new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "sayHelloProtectedResponse");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: ee.jakarta.tck.authentication.test.basic.soap
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link SayHelloProtected }
+ *
+ * @return
+ * the new instance of {@link SayHelloProtected }
+ */
+ public SayHelloProtected createSayHelloProtected() {
+ return new SayHelloProtected();
+ }
+
+ /**
+ * Create an instance of {@link SayHelloProtectedResponse }
+ *
+ * @return
+ * the new instance of {@link SayHelloProtectedResponse }
+ */
+ public SayHelloProtectedResponse createSayHelloProtectedResponse() {
+ return new SayHelloProtectedResponse();
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link SayHelloProtected }{@code >}
+ *
+ * @param value
+ * Java instance representing xml element's value.
+ * @return
+ * the new instance of {@link JAXBElement }{@code <}{@link SayHelloProtected }{@code >}
+ */
+ @XmlElementDecl(namespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", name = "sayHelloProtected")
+ public JAXBElement createSayHelloProtected(SayHelloProtected value) {
+ return new JAXBElement<>(_SayHelloProtected_QNAME, SayHelloProtected.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link SayHelloProtectedResponse }{@code >}
+ *
+ * @param value
+ * Java instance representing xml element's value.
+ * @return
+ * the new instance of {@link JAXBElement }{@code <}{@link SayHelloProtectedResponse }{@code >}
+ */
+ @XmlElementDecl(namespace = "http://soap.basic.test.authentication.tck.jakarta.ee/", name = "sayHelloProtectedResponse")
+ public JAXBElement createSayHelloProtectedResponse(SayHelloProtectedResponse value) {
+ return new JAXBElement<>(_SayHelloProtectedResponse_QNAME, SayHelloProtectedResponse.class, null, value);
+ }
+
+}
diff --git a/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtected.java b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtected.java
new file mode 100644
index 0000000..c052d6f
--- /dev/null
+++ b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtected.java
@@ -0,0 +1,60 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlType;
+
+
+/**
+ *
Java class for sayHelloProtected complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
{@code
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * }
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "sayHelloProtected", propOrder = {
+ "arg0"
+})
+public class SayHelloProtected {
+
+ protected String arg0;
+
+ /**
+ * Gets the value of the arg0 property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getArg0() {
+ return arg0;
+ }
+
+ /**
+ * Sets the value of the arg0 property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setArg0(String value) {
+ this.arg0 = value;
+ }
+
+}
diff --git a/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtectedResponse.java b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtectedResponse.java
new file mode 100644
index 0000000..47e8d0e
--- /dev/null
+++ b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/SayHelloProtectedResponse.java
@@ -0,0 +1,62 @@
+
+package ee.jakarta.tck.authentication.test.basic.soap;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlType;
+
+
+/**
+ *
Java class for sayHelloProtectedResponse complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
{@code
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * }
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "sayHelloProtectedResponse", propOrder = {
+ "_return"
+})
+public class SayHelloProtectedResponse {
+
+ @XmlElement(name = "return")
+ protected String _return;
+
+ /**
+ * Gets the value of the return property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getReturn() {
+ return _return;
+ }
+
+ /**
+ * Sets the value of the return property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setReturn(String value) {
+ this._return = value;
+ }
+
+}
diff --git a/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/package-info.java b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/package-info.java
new file mode 100644
index 0000000..0cb79e8
--- /dev/null
+++ b/tck/spi/soap/src/main/java/ee/jakarta/tck/authentication/test/basic/soap/package-info.java
@@ -0,0 +1,2 @@
+@jakarta.xml.bind.annotation.XmlSchema(namespace = "http://soap.basic.test.authentication.tck.jakarta.ee/")
+package ee.jakarta.tck.authentication.test.basic.soap;
diff --git a/tck/spi/soap/src/main/resources/META-INF/services/com.sun.xml.ws.assembler.metro.dev.ClientPipelineHook b/tck/spi/soap/src/main/resources/META-INF/services/com.sun.xml.ws.assembler.metro.dev.ClientPipelineHook
new file mode 100644
index 0000000..1d320b3
--- /dev/null
+++ b/tck/spi/soap/src/main/resources/META-INF/services/com.sun.xml.ws.assembler.metro.dev.ClientPipelineHook
@@ -0,0 +1 @@
+com.sun.enterprise.security.webservices.client.ClientSecurityPipeCreator
\ No newline at end of file
diff --git a/tck/spi/soap/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer b/tck/spi/soap/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer
new file mode 100644
index 0000000..7a4388c
--- /dev/null
+++ b/tck/spi/soap/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer
@@ -0,0 +1 @@
+ee.jakarta.tck.authentication.test.basic.servlet.AuthFactoryContainerInitializer
\ No newline at end of file
diff --git a/tck/spi/soap/src/main/webapp/WEB-INF/HelloService.wsdl b/tck/spi/soap/src/main/webapp/WEB-INF/HelloService.wsdl
new file mode 100644
index 0000000..7a83418
--- /dev/null
+++ b/tck/spi/soap/src/main/webapp/WEB-INF/HelloService.wsdl
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tck/spi/soap/src/main/webapp/WEB-INF/HelloService_schema1.xsd b/tck/spi/soap/src/main/webapp/WEB-INF/HelloService_schema1.xsd
new file mode 100644
index 0000000..94b5d77
--- /dev/null
+++ b/tck/spi/soap/src/main/webapp/WEB-INF/HelloService_schema1.xsd
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tck/spi/soap/src/main/webapp/WEB-INF/soap-web.xml b/tck/spi/soap/src/main/webapp/WEB-INF/soap-web.xml
new file mode 100644
index 0000000..c8cbc07
--- /dev/null
+++ b/tck/spi/soap/src/main/webapp/WEB-INF/soap-web.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+ soap_app
+
+
+ Hello
+ ee.jakarta.tck.authentication.test.basic.soap.HelloImpl
+ 0
+
+ ADM
+ Administrator
+
+
+
+ Hello
+ /Hello
+
+
+
+ 54
+
+
+
+ the administrator role
+ Administrator
+
+
diff --git a/tck/spi/soap/src/main/webapp/WEB-INF/web.xml b/tck/spi/soap/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..180833e
--- /dev/null
+++ b/tck/spi/soap/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ spi_servlet
+
+
+ BASIC
+ default
+
+
+
diff --git a/tck/spi/soap/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapProfileSPITest.java b/tck/spi/soap/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapProfileSPITest.java
new file mode 100644
index 0000000..3ee96ee
--- /dev/null
+++ b/tck/spi/soap/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapProfileSPITest.java
@@ -0,0 +1,878 @@
+package ee.jakarta.tck.authentication.test.basic;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.TSSV_ACF;
+import static jakarta.security.auth.message.config.AuthConfigFactory.DEFAULT_FACTORY_SECURITY_PROPERTY;
+import static org.junit.Assert.assertTrue;
+
+import com.sun.xml.ws.api.client.ClientPipelineHook;
+import ee.jakarta.tck.authentication.test.basic.soap.AuthFactoryContainerInitializer;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import ee.jakarta.tck.authentication.test.basic.soap.HelloService;
+import ee.jakarta.tck.authentication.test.common.ArquillianBase;
+import ee.jakarta.tck.authentication.test.common.logging.client.LogFileProcessor;
+import ee.jakarta.tck.authentication.test.common.logging.client.TestUtil;
+import jakarta.servlet.ServletContainerInitializer;
+import java.io.File;
+import java.net.URL;
+import java.security.Security;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import javax.xml.namespace.QName;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+/**
+ * This tests a large number of SPI assertions from the Servlet profile.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class SoapProfileSPITest extends ArquillianBase {
+
+ private static boolean setUpIsDone = false;
+
+ String logicalHostName = "localhost";
+ String expectedAppContextId = "localhost /Hello_web/Hello";
+
+ // this must be the decoded context path corresponding to the web module
+ private String contextPath = "/" + JASPICData.SCP_CONTEXT_PATH;
+ private String openToAllServletPath = "OpenToAllServlet";
+
+ private String appContext = System.getProperty("logical.hostname.servlet") + " " + contextPath;
+
+ LogFileProcessor logProcessor = new LogFileProcessor();
+ LogFileProcessor clientLogProcessor = new LogFileProcessor(true);
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ WebArchive archive = defaultWebArchive("Hello_web");
+ archive.addAsServiceProvider(ServletContainerInitializer.class, AuthFactoryContainerInitializer.class);
+ archive.addAsWebInfResource(resource("soap-web.xml"), "web.xml");
+
+ File file = new File(System.getProperty("log.file.location"), "authentication-trace-log.xml");
+ if (file.exists()) {
+ System.out.println("deleting " + file.toString());
+ file.delete();
+ }
+
+ file = new File(System.getProperty("log.file.location"), "authentication-trace-log.xml.lck");
+ if (file.exists()) {
+ file.delete();
+ }
+
+ System.out.println(archive.toString(true));
+
+ return archive;
+ }
+
+
+ @Before
+ public void runOnce() throws Exception {
+ if (setUpIsDone) {
+ return;
+ }
+
+ Security.setProperty(DEFAULT_FACTORY_SECURITY_PROPERTY, TSSV_ACF);
+ Optional optionalHook = ServiceLoader.load(ClientPipelineHook.class).findFirst();
+ if (optionalHook.isPresent()) {
+ int a;
+ a = 4;
+ }
+
+ HelloService helloService = new HelloService(
+ new URL(getBase(), "Hello?wsdl"),
+ new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloService"));
+
+ String text = helloService.getHelloPort().sayHelloProtected("Raja");
+ TestUtil.logMsg("Got Output : " + text);
+
+ logProcessor.fetchLogs();
+
+ setUpIsDone = true;
+ }
+
+ @Before
+ public void fetchLogs() {
+ logProcessor.fetchLogs();
+ clientLogProcessor.fetchLogs();
+ }
+
+
+ // ### Client side tests
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ValidateResponse
+ *
+ * @assertion_ids: JASPIC:SPEC:42
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether ClientAuthContext.validateResponse() is called
+ *
+ * Description The runtime must invoke ClientAuthContext.validateResponse()
+ *
+ */
+ @Test
+ public void ValidateResponse() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ "validateResponse failed : " + "ClientAuthContext.validateResponse not called",
+ clientLogProcessor.verifyLogContains("TSClientAuthContext.validateResponse called"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ClientAuthContext
+ *
+ * @assertion_ids: JASPIC:SPEC:34; JASPIC:JAVADOC:72; JASPIC:JAVADOC:97; JASPIC:JAVADOC:98
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether ClientAuthConfig.getAuthContext() is called
+ *
+ * Description The runtime must invoke clientAuthConfig().getAuthContext() to obtain the ClientAuthContext.
+ *
+ */
+ @Test
+ public void ClientAuthContext() {
+ String args[] = { "service/HelloService", getBase() + "Hello" };
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "ClientAuthContext failed : " + "clientAuthConfig.getAuthContext not called",
+ clientLogProcessor.verifyLogContainsOneOfSubString(args, "TSClientAuthConfig.getAuthContext: layer=SOAP : appContext="));
+ }
+
+ /**
+ * @testName: NameAndPasswordCallbackSupport
+ *
+ * @assertion_ids: JASPIC:SPEC:123; JASPIC:JAVADOC:103
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether CallbackHandler for client runtime supports
+ * NameCallback and PasswordCallback
+ *
+ * Description Unless the client runtime is embedded in a server runtime (e.g.; an invocation of a web service by a
+ * servlet running in a Servlet container), The CallbackHandler passed to ClientAuthModule.initialize must support the
+ * following callbacks: NameCallback, PasswordCallback
+ *
+ */
+ @Test
+ public void NameAndPasswordCallbackSupport() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContains(
+ "In SOAP : ClientRuntime CallbackHandler supports NameCallback",
+ "In SOAP : ClientRuntime CallbackHandler supports PasswordCallback"));
+ }
+
+ /**
+ * @testName: ClientRuntimeCommonCallbackSupport
+ *
+ * @assertion_ids: JASPIC:SPEC:114; JASPIC:JAVADOC:35; JASPIC:JAVADOC:36; JASPIC:JAVADOC:49; JASPIC:JAVADOC:51;
+ * JASPIC:JAVADOC:54; JASPIC:JAVADOC:63; JASPIC:JAVADOC:65; JASPIC:JAVADOC:68; JASPIC:JAVADOC:69; JASPIC:JAVADOC:71;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether CallbackHandler for client runtime supports
+ * CertStoreCallback, PrivateKeyCallback, SecretKeyCallback, TrustStoreCallback
+ *
+ * Description
+ *
+ * The CallbackHandler passed to the initialize method of an authentication module should support the following
+ * callbacks, and it must be possible to configure the runtime such that the CallbackHandler passed at module
+ * initialization module supports the following callbacks (in addition to any others required to be supported by the
+ * applicable internal profile): CertStoreCallback, PrivateKeyCallback, SecretKeyCallback, TrustStoreCallback
+ *
+ *
+ */
+ @Test
+ public void ClientRuntimeCommonCallbackSupport() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContains(
+ "In SOAP : ClientRuntime CallbackHandler supports CertStoreCallback",
+ "In SOAP : ClientRuntime CallbackHandler supports PrivateKeyCallback",
+ "In SOAP : ClientRuntime CallbackHandler supports SecretKeyCallback",
+ "In SOAP : ClientRuntime CallbackHandler supports TrustStoreCallback"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACPClientAuthConfig
+ *
+ * @assertion_ids: JASPIC:SPEC:124; JASPIC:JAVADOC:77
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether the arguments(layer and appcontextId) passed to
+ * obtain AuthConfigProvider is same as the arguments used in calling getClientAuthConfig.
+ *
+ * Description
+ *
+ * If a non-null AuthConfigProvider is returned (by the call to getConfigProvider), the messaging runtime must call
+ * getClientAuthConfig on the provider to obtain the authentication context configuration object pertaining to the
+ * application context at the layer. The layer and appContext arguments of the call to getClientAuthConfig must be the
+ * same as those used to acquire the provider.
+ *
+ *
+ */
+ @Test
+ public void ACPClientAuthConfig() {
+ String args[] = { "service/HelloService", getBase() + "Hello" };
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContainsOneOfSubString(args, "TSAuthConfigFactory.getConfigProvider returned non-null provider for" + " Layer : SOAP and AppContext :"));
+
+ // ACPClientAuthConfig : Same layer and appContextId used
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContainsOneOfSubString(args, "TSAuthConfigProvider.getClientAuthConfig called for " + "layer=SOAP : appContext="));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: CACRequestResponse
+ *
+ * @assertion_ids: JASPIC:SPEC:130; JASPIC:JAVADOC:7; JASPIC:JAVADOC:9; JASPIC:SPEC:19; JASPIC:SPEC:23; JASPIC:SPEC:129;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify whether for a non-null ClientAuthContext, secureRequest
+ * and validateResponse are called properly.
+ *
+ * Description
+ *
+ * If the client runtime obtained a non-null ClientAuthContext by using the operation identifier corresponding to the
+ * request message, then at point (1) in the message processing model, the runtime must call secureRequest on the
+ * ClientAuthContext, and at point (4) the runtime must call validateResponse on the ClientAuthContext.
+ *
+ *
+ */
+ @Test
+ public void CACRequestResponse() {
+ // Verify whether the log contains required messages.
+ assertTrue(clientLogProcessor.verifyLogContains(
+ "TSClientAuthConfig.getAuthContext: returned non-null" + " ClientAuthContext for operationId=sayHelloProtected",
+ "TSClientAuthContext.secureRequest called",
+ "TSClientAuthContext.validateResponse called"));
+ }
+
+
+
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ClientRuntimeMessageInfoMap
+ *
+ * @assertion_ids: JASPIC:SPEC:133; JASPIC:JAVADOC:7
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify whether the Map in messageInfo object passed to
+ * secureRequest and validateResponse contains the right value for key jakarta.xml.ws.wsdl.service
+ *
+ * Description This profile requires that the message processing runtime establish the following key-value pairs within
+ * the Map of the MessageInfo passed in the calls to secureRequest and validateResponse Key=jakarta.xml.ws.wsdl.service
+ * Value= the value of the qualified service name, represented as a javax.xml.namespace.QName
+ *
+ */
+ @Test
+ public void ClientRuntimeMessageInfoMap() {
+ QName expectedQName = new QName("http://soap.basic.test.authentication.tck.jakarta.ee/", "HelloService");
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContains(
+ "TSClientAuthModule.secureRequest messageInfo :" + "jakarta.xml.ws.wsdl.service=" + expectedQName.toString(),
+ "TSClientAuthModule.validateResponse messageInfo :" + "jakarta.xml.ws.wsdl.service=" + expectedQName.toString()));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ClientAppContextId
+ *
+ * @assertion_ids: JASPIC:SPEC:208
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify whether for the client side appilcation context
+ * Identifier is correctly used by the runtime.
+ *
+ * Description A Client application context Identifier must be the String value composed by concatenating the client
+ * scope identifier, a blank separator character, and the client reference to the service. The clien scope identifier is
+ * not testable but we can check the client reference to the service.
+ *
+ */
+ @Test
+ public void ClientAppContextId() {
+ String args[] = { "service/HelloService", getBase() + "Hello" };
+
+ // Verify whether the log contains required messages.
+ assertTrue(
+ clientLogProcessor.verifyLogContainsOneOfSubString(args,
+ "TSAuthConfigProvider.getClientAuthConfig called for " + "layer=SOAP : appContext="));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ClientAuthConfig
+ *
+ * @assertion_ids: JASPIC:SPEC:11; JASPIC:SPEC:12 ; JASPIC:SPEC:16;
+ * JASPIC:JAVADOC:92; JASPIC:JAVADOC:93; JASPIC:SPEC:110;
+ * JASPIC:SPEC:111
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether AuthConfigProvider.ClientAuthConfig is
+ * called in the server.
+ *
+ * Description The runtime must invoke
+ * AuthConfigProvider.getClientAuthConfig() to obtain the
+ * AuthConfig. The runtime must also specify
+ * appropriate(non-null) layer(i.e for this test case "SOAP"
+ * layer) and application context identifiers in its call to
+ * getClientAuthConfig.
+ *
+ */
+ @Test
+ public void ClientAuthConfig() {
+ String args[] = { "service/HelloService", getBase() + "Hello" };
+
+ // verify whether the log contains required messages.
+ assertTrue(
+ "ClientAuthConfig failed : " + "AuthConfigProvider.getClientAuthConfig not called",
+ clientLogProcessor.verifyLogContainsOneOfSubString(args,
+ "TSAuthConfigProvider.getClientAuthConfig called for layer=SOAP : appContext="));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: SecureRequest
+ *
+ * @assertion_ids: JASPIC:SPEC:35; JASPIC:JAVADOC:5; JASPIC:SPEC:36;
+ * JASPIC:JAVADOC:75
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether ClientAuthContext.secureRequest() is called
+ *
+ * Description The runtime must invoke
+ * ClientAuthContext.secureRequest()
+ *
+ */
+ @Test
+ public void SecureRequest() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "SecureRequest failed : " + "ClientAuthContext.secureRequest not called",
+ clientLogProcessor.verifyLogContains("TSClientAuthContext.secureRequest called"));
+ }
+
+
+
+ // ### Server side ###
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: GetConfigProvider
+ *
+ * @assertion_ids: JASPIC:SPEC:8; JASPIC:SPEC:14; JASPIC:SPEC:116; JASPIC:SPEC:117; JASPIC:JAVADOC:77;
+ * JASPIC:JAVADOC:79; JASPIC:JAVADOC:80; JASPIC:JAVADOC:84; JASPIC:JAVADOC:85; JASPIC:JAVADOC:91; JASPIC:SPEC:110;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to verify Whether AuthConfigFactory.getConfigProvider is called
+ * in the server.
+ *
+ * Description The runtime must invoke AuthConfigFactory.getConfigProvider to obtain the AuthConfigProvider. The runtime
+ * must also specify appropriate(non-null) layer and application context identifiers in its call to getConfigProvider.
+ *
+ */
+ @Test
+ public void GetConfigProvider() {
+ assertTrue(
+ "GetConfigProvider failed : " + "AuthConfigFactory.getConfigProvider not called",
+ logProcessor.verifyLogContains(
+ "TSAuthConfigFactory.getConfigProvider called",
+ "getConfigProvider called for Layer : SOAP and AppContext :" + expectedAppContextId ));
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: GetFactory
+ *
+ * @assertion_ids: JASPIC:SPEC:7; JASPIC:SPEC:10; JASPIC:JAVADOC:77;
+ * JASPIC:JAVADOC:80; JASPIC:JAVADOC:84; JASPIC:JAVADOC:79;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether AuthConfigFactory.getConfigProvider is
+ * called in the server.
+ *
+ * Description The runtime must invoke
+ * AuthConfigFactory.getConfigProvider to obtain the
+ * AuthConfigProvider. By calling getConfigProvider, we can
+ * assume getFactory() was called.
+ *
+ */
+ @Test
+ public void GetFactory() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "GetFactory failed : " + "AuthConfigFactory.getFactory not called",
+ logProcessor.verifyLogContains("TSAuthConfigFactory.getFactory called Indirectly"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ServerAuthConfig
+ *
+ * @assertion_ids: JASPIC:SPEC:11; JASPIC:SPEC:13 ; JASPIC:SPEC:16;
+ * JASPIC:JAVADOC:95
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether provider.getServerAuthConfig is called in
+ * the server.
+ *
+ * Description The runtime must invoke
+ * AuthConfigProvider.getServerAuthConfig() to obtain the
+ * AuthConfig. The runtime must also specify
+ * appropriate(non-null) layer(i.e for this test case "SOAP"
+ * layer) and application context identifiers in its call to
+ * getServerAuthConfig.
+ *
+ */
+ @Test
+ public void ServerAuthConfig() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "ServerAuthConfig failed : " + "AuthConfigProvider.getServerAuthConfig not called",
+ logProcessor.verifyLogContains(
+ "TSAuthConfigProvider.getServerAuthConfig called for layer=SOAP" +
+ " : appContext=" + expectedAppContextId));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ValidateRequest
+ *
+ * @assertion_ids: JASPIC:SPEC:50; JASPIC:JAVADOC:16; JASPIC:JAVADOC:17;
+ * JASPIC:JAVADOC:23; JASPIC:SPEC:23; JASPIC:SPEC:19
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether ServerAuthContext.validateRequest() is
+ * called
+ *
+ * Description The runtime must invoke
+ * ServerAuthContext.validateRequest()
+ *
+ */
+ @Test
+ public void ValidateRequest() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ "ValidateRequest failed : " + "ServerAuthContext.validateRequest not called",
+ logProcessor.verifyLogContains("TSServerAuthContext.validateRequest called"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: SecureResponse
+ *
+ * @assertion_ids: JASPIC:SPEC:59; JASPIC:JAVADOC:16; JASPIC:JAVADOC:17;
+ * JASPIC:JAVADOC:23; JASPIC:JAVADOC:26
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether ServerAuthContext.secureResponse() is called
+ *
+ * Description The runtime must invoke
+ * ServerAuthContext.secureResponse()
+ *
+ */
+ @Test
+ public void SecureResponse() {
+ // verify whether the log contains required messages.
+ assertTrue("SecureResponse failed : " + "ServerAuthContext.secureResponse not called",
+ logProcessor.verifyLogContains("TSServerAuthContext.secureResponse called"));
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ServerAuthContext
+ *
+ * @assertion_ids: JASPIC:SPEC:34; JASPIC:JAVADOC:100; JASPIC:SPEC:153;
+ * JASPIC:SPEC:156; JASPIC:JAVADOC:101
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether ServerAuthConfig.getAuthContext() is called
+ *
+ * Description The runtime must invoke
+ * serverAuthConfig().getAuthContext() to obtain the
+ * ServerAuthContext.
+ *
+ */
+ @Test
+ public void ServerAuthContext() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ "TSServerAuthConfig.getAuthContext: layer=SOAP : appContext=" + expectedAppContextId,
+ logProcessor.verifyLogContains(
+ "TSServerAuthConfig.getAuthContext: layer=SOAP : appContext=" + expectedAppContextId));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: MessageInfo
+ *
+ * @assertion_ids: JASPIC:SPEC:35; JASPIC:SPEC:44; JASPIC:JAVADOC:5;
+ * JASPIC:SPEC:112; JASPIC:JAVADOC:9; JASPIC:JAVADOC:10;
+ * JASPIC:JAVADOC:11; JASPIC:JAVADOC:28; JASPIC:SPEC:23;
+ * JASPIC:SPEC:19; JASPIC:SPEC:36; JASPIC:SPEC:37;
+ * JASPIC:SPEC:43; JASPIC:SPEC:51; JASPIC:SPEC:113;
+ * JASPIC:SPEC:131; JASPIC:SPEC:132;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether the messageInfo passed to secureRequest()
+ * validateRequest(), secureResponse() and validateResponse()
+ * contiains right values for getRequestMessage() and
+ * getResponseMessage() as per the spec.
+ *
+ * 3. clientSubject - a Subject that represents the source of
+ * the service request, or null.
+ *
+ * Description The MessageInfo argument used in any call made
+ * by the message processing runtime to secureRequest,
+ * validateResponse, validateRequest, or secureResponse must
+ * have been initialized such that the non-null objects
+ * returned by the getRequestMessage and getResponseMessage
+ * methods of the MessageInfo are an instanceof
+ * jakarta.xml.soap.SOAPMessage.
+ *
+ *
+ */
+ @Test
+ public void MessageInfo() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ "MessageInfo failed : " + "The request and response messages contains incorrect values",
+ logProcessor.verifyLogContains(
+ // "secureRequest : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage",
+ "validateRequest : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage",
+ "secureResponse : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage",
+ "secureResponse : MessageInfo.getResponseMessage() is of type jakarta.xml.soap.SOAPMessage"
+
+
+ ));
+
+ // "validateResponse : MessageInfo.getRequestMessage() is of type jakarta.xml.soap.SOAPMessage",
+ //"validateResponse : MessageInfo.getResponseMessage() is of type jakarta.xml.soap.SOAPMessage"
+ }
+
+ /**
+ * @testName: ServerRuntimeCommonCallbackSupport
+ *
+ * @assertion_ids: JASPIC:SPEC:114; JASPIC:JAVADOC:35; JASPIC:JAVADOC:36;
+ * JASPIC:JAVADOC:49; JASPIC:JAVADOC:51; JASPIC:JAVADOC:54;
+ * JASPIC:JAVADOC:63; JASPIC:JAVADOC:65; JASPIC:JAVADOC:68;
+ * JASPIC:JAVADOC:69; JASPIC:JAVADOC:71; JASPIC:JAVADOC:106
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether CallbackHandler for server runtime supports
+ * CertStoreCallback, PrivateKeyCallback, SecretKeyCallback,
+ * TrustStoreCallback
+ *
+ * Description
+ *
+ * The CallbackHandler passed to the initialize method of an
+ * authentication module should support the following
+ * callbacks, and it must be possible to configure the runtime
+ * such that the CallbackHandler passed at module
+ * initialization module supports the following callbacks (in
+ * addition to any others required to be supported by the
+ * applicable internal profile): CertStoreCallback,
+ * PrivateKeyCallback, SecretKeyCallback, TrustStoreCallback
+ *
+ *
+ */
+ @Test
+ public void ServerRuntimeCommonCallbackSupport() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "In SOAP : ServerRuntime CallbackHandler supports CertStoreCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports PrivateKeyCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports SecretKeyCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports TrustStoreCallback"));
+ }
+
+ /**
+ * @testName: ServerRuntimeCallbackSupport
+ *
+ * @assertion_ids: JASPIC:SPEC:114; JASPIC:SPEC:149; JASPIC:JAVADOC:38;
+ * JASPIC:JAVADOC:39; JASPIC:JAVADOC:40; JASPIC:JAVADOC:42;
+ * JASPIC:JAVADOC:43; JASPIC:JAVADOC:44; JASPIC:JAVADOC:46;
+ * JASPIC:JAVADOC:30; JASPIC:JAVADOC:41; JASPIC:JAVADOC:45
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether CallbackHandler for server runtime supports
+ * CallerPrincipalCallback, GroupPrincipalCallback and
+ * PasswordValidationCallback
+ *
+ * Description
+ *
+ * The CallbackHandler passed to the
+ * ServerAuthModule.initialize must support the following
+ * callbacks,
+ *
+ * CallerPrincipalCallback, GroupPrincipalCallback,
+ * PasswordValidationCallback
+ *
+ *
+ */
+ @Test
+ public void ServerRuntimeCallbackSupport() {
+ // Verify whether the log contains required messages.
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "In SOAP : ServerRuntime CallbackHandler supports CallerPrincipalCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports GroupPrincipalCallback",
+ "In SOAP : ServerRuntime CallbackHandler supports PasswordValidationCallback"));
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: OperationId
+ *
+ * @assertion_ids: JASPIC:SPEC:121; JASPIC:SPEC:125; JASPIC:JAVADOC:73
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether the operationId is "sayHelloProtected"
+ *
+ * Description
+ *
+ * If getOperation returns a non-null operation identifier,
+ * then the operation identifier must be the String value
+ * corresponding to the operation name appearing in the
+ * service description (i.e., WSDL).
+ *
+ * When its getOperation method is called, any authentication
+ * context configuration object obtained for the SOAP layer,
+ * must attempt to derive the corresponding operation
+ * identifier value from the request message (within
+ * messageInfo).
+ *
+ *
+ */
+ @Test
+ public void OperationId() {
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "getAuthContextID() called for layer=SOAP shows AuthContextId=" +
+ "sayHelloProtected"));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACPAuthContext
+ *
+ * @assertion_ids: JASPIC:SPEC:125; JASPIC:SPEC:150; JASPIC:JAVADOC:5;
+ * JASPIC:JAVADOC:28; JASPIC:JAVADOC:73; JASPIC:JAVADOC:79
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether the arguments(operation) passed to obtain
+ * getAuthContext is same as defined in Section 4.7.1
+ *
+ * Description The authentication context identifier used in
+ * the call to getAuthContext must be equivalent to the value
+ * that would be acquired by calling getAuthContextID with the
+ * MessageInfo that will be used in the corresponding call to
+ * secureRequest (by a client runtime) or validateRequest (by
+ * a server runtime).
+ *
+ */
+ @Test
+ public void ACPAuthContext() {
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "TSAuthConfigFactory.getConfigProvider returned non-null provider for" + " Layer : SOAP and AppContext :" + expectedAppContextId,
+ "TSServerAuthConfig.getAuthContext: layer=SOAP" + " : appContext=" + expectedAppContextId + " operationId=sayHelloProtected"));
+
+
+// String cArgs[] = { "service/HelloService",
+// "http://" + hostname + ":" + portnum + "/Hello_web/Hello" };
+//
+// // verify whether the log contains required messages.
+// logProcessor.verifyLogContainsOneOfSubString(cArgs,
+// "TSClientAuthConfig.getAuthContext: layer=SOAP"
+// + " : appContext=");
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACPServerAuthConfig
+ *
+ * @assertion_ids: JASPIC:SPEC:150; JASPIC:JAVADOC:79; JASPIC:JAVADOC:94
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify Whether the arguments(layer and appcontextId) passed
+ * to obtain AuthConfigProvider is same as the arguments used
+ * in calling getServerAuthConfig.
+ *
+ * Description
+ *
+ * If a non-null AuthConfigProvider is returned (by the call
+ * to getConfigProvider), the messaging runtime must call
+ * getServerAuthConfig on the provider to obtain the
+ * authentication context configuration object pertaining to
+ * the application context at the layer. The layer and
+ * appContext arguments of the call to getServerAuthConfig
+ * must be the same as those used to acquire the provider.
+ *
+ *
+ */
+ public void ACPServerAuthConfig() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "TSAuthConfigFactory.getConfigProvider returned non-null provider for" + " Layer : SOAP and AppContext :" + expectedAppContextId,
+ "TSAuthConfigProvider.getServerAuthConfig called for " + "layer=SOAP : appContext=" + expectedAppContextId ));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: SACRequestResponse
+ *
+ * @assertion_ids: JASPIC:SPEC:130; JASPIC:JAVADOC:13; JASPIC:JAVADOC:16;
+ * JASPIC:JAVADOC:17; JASPIC:JAVADOC:23; JASPIC:JAVADOC:26;
+ * JASPIC:JAVADOC:28; JASPIC:SPEC:155;
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify whether for a non-null ServerAuthContext,
+ * validateRequest and secureResponse are called properly.
+ *
+ * Description
+ *
+ * If the server runtime obtained a non-null ServerAuthContext
+ * by using the operation identifier corresponding to the
+ * request message, then at point (2) in the message
+ * processing model, the runtime must call validateRequest on
+ * the ClientAuthContext, and at point (3) the runtime must
+ * call secureResponse on the ServerAuthContext.
+ *
+ *
+ */
+ public void SACRequestResponse() {
+ // verify whether the log contains required messages.
+ assertTrue(
+ logProcessor.verifyLogContains(
+ "TSServerAuthConfig.getAuthContext: returned non-null" + " ServerAuthContext for operationId=sayHelloProtected",
+ "TSServerAuthContext.validateRequest called",
+ "TSServerAuthContext.secureResponse called" ));
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ServerAppContextId
+ *
+ * @assertion_ids: JASPIC:SPEC:209
+ *
+ * @test_Strategy: 1. Register TSSV with the AppServer. (See User guide for
+ * Registering TSSV with your AppServer ).
+ *
+ * 2. Use FetchLog servlet to read the server side log to
+ * verify whether for the server side appilcation context
+ * Identifier is correctly used by the runtime.
+ *
+ * Description A server application context Identifier shall
+ * be the String value composed by concatenating a logical
+ * hostname a blank separator character, and the path
+ * component of the service endpoint URI corresponding to the
+ * webservice.
+ */
+ @Test
+ public void ServerAppContextId() {
+ String args[] = {
+ logicalHostName + " /Hello_web/Hello" };
+
+ // verify whether the log contains required messages.
+ assertTrue(logProcessor.verifyLogContainsOneOfSubString(args,
+ "TSAuthConfigProvider.getServerAuthConfig called for " + "layer=SOAP : appContext="));
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/tck/spi/soap/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapUnitTest.java b/tck/spi/soap/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapUnitTest.java
new file mode 100644
index 0000000..a807597
--- /dev/null
+++ b/tck/spi/soap/src/test/java/ee/jakarta/tck/authentication/test/basic/SoapUnitTest.java
@@ -0,0 +1,606 @@
+package ee.jakarta.tck.authentication.test.basic;
+
+import static ee.jakarta.tck.authentication.test.basic.servlet.JASPICData.TSSV_ACF;
+import static jakarta.security.auth.message.config.AuthConfigFactory.DEFAULT_FACTORY_SECURITY_PROPERTY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationEntry;
+import ee.jakarta.tck.authentication.test.basic.sam.ProviderConfigurationXMLFileProcessor;
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSAuthConfigFactoryForStandalone;
+import ee.jakarta.tck.authentication.test.basic.sam.config.TSRegistrationListener;
+import ee.jakarta.tck.authentication.test.basic.servlet.CommonTests;
+import ee.jakarta.tck.authentication.test.basic.servlet.JASPICData;
+import jakarta.security.auth.message.config.AuthConfigFactory;
+import jakarta.security.auth.message.config.AuthConfigProvider;
+import jakarta.security.auth.message.config.RegistrationListener;
+import java.security.Security;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.logging.Logger;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SoapUnitTest {
+
+ Logger logger = Logger.getLogger(SoapUnitTest.class.getName());
+
+ private String logFileLocation = System.getProperty("log.file.location");
+ private String providerConfigFileLocation = System.getProperty("provider.configuration.file");
+ private String vendorACFClass = System.getProperty("vendor.authconfig.factory");
+ private String soapAppContext = "localhost /Hello_web/Hello";
+
+ private transient ProviderConfigurationXMLFileProcessor configFileProcessor;
+
+ private Collection providerConfigurationEntriesCollection;
+
+ private CommonTests commonTests = new CommonTests();
+
+ @Before
+ public void setup() {
+ AuthConfigFactory.setFactory(null);
+ Security.setProperty(DEFAULT_FACTORY_SECURITY_PROPERTY, TSSV_ACF);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFGetFactory
+ *
+ * @assertion_ids: JASPIC:SPEC:329; JASPIC:SPEC:335; JASPIC:SPEC:7;
+ *
+ * @test_Strategy: This s mainly concerned with testing the runtimes handling of ACF as follows: - get current (CTS) ACF
+ * - switch to use different (CTS) ACF - verify calls to ACF use the newer/expected ACF - restore original ACF
+ */
+ @Test
+ public void ACFGetFactory() {
+ boolean passed = false;
+ try {
+ commonTests._ACF_getFactory();
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ *
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFSwitchFactorys
+ *
+ * @assertion_ids:
+ *
+ *
+ * @test_Strategy: This test does the following: - gets current (CTS) factory - sets the vendors ACF thus replacing the
+ * CTS ACF - verify ACF's were correctly set - reset factory back to the original CTS factory
+ *
+ * 1. Use the static setFactory method to set an ACF and this should always work. and use the getFactory to verify it
+ * worked.
+ *
+ * Description
+ *
+ */
+ @Test
+ public void ACFSwitchFactorys() {
+ boolean passed = false;
+ try {
+ commonTests._ACFSwitchFactorys(vendorACFClass);
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: testACFComesFromSecFile
+ *
+ * @assertion_ids: JASPIC:SPEC:329; JASPIC:SPEC:330;
+ *
+ * @test_Strategy: This is calling a method on the server(actually servlet) side that will invoke getFactory() to verify
+ * a non-null facotry instance is returned. It will also verify that the authconfigprovider.factory security property is
+ * properly set/used.
+ *
+ */
+ @Test
+ public void testACFComesFromSecFile() {
+ boolean passed = false;
+ try {
+ commonTests._testACFComesFromSecFile();
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFPersistentRegisterOnlyOneACP
+ *
+ * @assertion_ids: JASPIC:SPEC:329; JASPIC:SPEC:331; JASPIC:SPEC:332; JASPIC:SPEC:340; JASPIC:SPEC:341;
+ *
+ * @test_Strategy: This will make a server (actually servlet) side method call that will do the following: - load
+ * vendors ACF - (persistent) register of CTS ACP's in the vendors ACF - get list of vendors registered provider ID's -
+ * register another persistent ACP (this is standalone ACP profile) - verify another regId was added for standalone ACP
+ * - try to re-register (persistently) standalone provider - verify 2nd attempt at added standalone provider REPLACED
+ * the first but it should NOT have added another nor failed. - also confirm that regID for standalone ACP stayed the
+ * same after 1st and 2nd attempt to register standalone ACP - verify that the 2nd re-registering of ACP replaced the
+ * ACP AND the description. - unregister standalone ACP and setFactory back to CTS default
+ *
+ */
+ @Test
+ public void ACFPersistentRegisterOnlyOneACP() {
+ boolean passed = false;
+ try {
+ commonTests._ACFRegisterOnlyOneACP(logFileLocation, providerConfigFileLocation, vendorACFClass, true);
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFInMemoryRegisterOnlyOneACP
+ *
+ * @assertion_ids: JASPIC:SPEC:334; JASPIC:SPEC:342; JASPIC:SPEC:343;
+ *
+ * @test_Strategy: This will make a server (actually servlet) side method call that will do the following: - load
+ * vendors ACF - (persistent) register of CTS ACP's in the vendors ACF - get list of vendors registered provider ID's -
+ * register (in-memory) ACP (this is standalone ACP profile) - verify another regId was added for standalone ACP - try
+ * to re-register (in-memory) standalone provider - verify 2nd attempt at added standalone provider REPLACED the first
+ * but it should NOT have added another nor failed. - also confirm that regID for standalone ACP stayed the same after
+ * 1st and 2nd attempt to register standalone ACP - verify that the 2nd re-registering of ACP replaced the ACP AND the
+ * description. - unregister standalone ACP and setFactory back to CTS default
+ *
+ */
+ @Test
+ public void ACFInMemoryRegisterOnlyOneACP() {
+ boolean passed = false;
+ try {
+ commonTests._ACFRegisterOnlyOneACP(logFileLocation, providerConfigFileLocation, vendorACFClass, false);
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFUnregisterACP
+ *
+ * @assertion_ids: JASPIC:SPEC:344;
+ *
+ * @test_Strategy: This will make a server (actually servlet) side method call that will do the following: - load
+ * vendors ACF - (persistent) register of CTS ACP's in the vendors ACF - get list of vendors registered provider ID's -
+ * register (in-memory) ACP (this is standalone ACP profile) - verify another regId was added for standalone ACP -
+ * unregister the in-memory ACP we just registered - verify removeRegistration() method call returned proper boolean -
+ * verify expected # of registry eentries - verify 2nd call to removeRegistration() with regId that was previously
+ * removed and should expect return val of false
+ *
+ */
+ @Test
+ public void ACFUnregisterACP() {
+ boolean passed = false;
+ try {
+ commonTests._ACFUnregisterACP(logFileLocation, providerConfigFileLocation, vendorACFClass);
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ *
+ * @keywords: jaspic_soap
+ *
+ * @testName: ACFRemoveRegistrationWithBadId
+ *
+ * @assertion_ids: JASPIC:SPEC:345;
+ *
+ *
+ * @test_Strategy: This test verifies we get a return value of False when invoking ACF.removeRegistration(some_bad_id);
+ *
+ * 1. Use the static setFactory method to get an ACF and then attempt to invoke removeRegistration() with an invalid (ie
+ * non-existant) regId. This should return False (per javadoc).
+ *
+ * Description
+ *
+ */
+ @Test
+ public void ACFRemoveRegistrationWithBadId() {
+ boolean passed = false;
+ try {
+ commonTests._ACFRemoveRegistrationWithBadId();
+ passed = true;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ assertTrue(passed);
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: getRegistrationContextId
+ *
+ * @assertion_ids: JASPIC:JAVADOC:77
+ *
+ * @test_Strategy: 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Use the system properties to read the TestSuite providers defined in ProviderConfigruation.xml file and register
+ * them with vendor's authconfig factory.
+ *
+ *
+ * Description This will use an appContext value that was used to register a provider, and it will see if it can use the
+ * AuthConfigFactory.RegistrationContext API to try and access the same appContext value that was used during the
+ * registration process.
+ *
+ */
+ @Test
+ public void getRegistrationContextId() {
+ String appContext = "localhost /Hello_web/Hello";
+
+ // register providers in vendor factory
+ assertTrue(register(logFileLocation, providerConfigFileLocation, vendorACFClass));
+
+ // verify we can access a given provider (any provider) appcontext id
+ boolean bVerified = false;
+
+ AuthConfigFactory acf = null;
+
+ try {
+ acf = AuthConfigFactory.getFactory();
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory.";
+ msg = msg + " Check your server side security policies.";
+ logger.info(msg);
+ ex.printStackTrace();
+ }
+
+ assertNotNull(
+ "getRegistrationContextId failed : could not get acf",
+ acf);
+
+
+ String[] regIDs = acf.getRegistrationIDs(null);
+ for (int ii = 0; ii < regIDs.length; ii++) {
+ // loop through the ACF's registration ids
+
+ if (regIDs[ii] != null) {
+ AuthConfigFactory.RegistrationContext acfReg;
+ acfReg = acf.getRegistrationContext(regIDs[ii]);
+ if (acfReg != null) {
+ logger.info("appContext = " + appContext);
+ logger.info("acfReg.getAppContext() = " + acfReg.getAppContext());
+ logger.info("layer = " + acfReg.getMessageLayer());
+ String str = acfReg.getAppContext();
+ if ((str != null) && (str.equals(appContext))) {
+ // we found our provider info
+ logger.info("Found it : RegistrationID for our ACP=" + regIDs[ii]);
+ bVerified = true;
+ break;
+ }
+ }
+ }
+ }
+
+ String msg = "Could not find appContext=" + appContext;
+ msg += " in the ACF's list of registration id info";
+
+ assertTrue(msg, bVerified);
+
+ logger.info("TestSuite Providers registration successful");
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: AuthConfigFactoryRegistration
+ *
+ * @assertion_ids: JASPIC:JAVADOC:80
+ *
+ * @test_Strategy: 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Use the system properties to read the TestSuite providers defined in ProviderConfigruation.xml file and register
+ * them with vendor's authconfig factory.
+ *
+ *
+ * Description
+ *
+ *
+ */
+ @Test
+ public void AuthConfigFactoryRegistration() {
+ assertTrue(
+ register(logFileLocation, providerConfigFileLocation, vendorACFClass));
+ }
+
+ public boolean register(String logFileLocation, String providerConfigFileLocation, String vendorACFClass) {
+ try {
+ printVerticalIndent();
+
+ // Get an instance of Vendor's AuthConfigFactory
+ AuthConfigFactory vendorFactory = getVendorAuthConfigFactory(vendorACFClass);
+
+ // Set vendor's AuthConfigFactory
+ AuthConfigFactory.setFactory(vendorFactory);
+
+ // Get system default AuthConfigFactory
+ AuthConfigFactory systemAuthConfigFactory = AuthConfigFactory.getFactory();
+
+ if (systemAuthConfigFactory != null) {
+ logger.info("Default AuthConfigFactory class name = " + systemAuthConfigFactory.getClass().getName());
+
+ } else {
+ logger.severe("Default AuthConfigFactory is null" + " can't register TestSuite Providers with null");
+ return false;
+ }
+
+ /**
+ * Read the ProviderConfiguration XML file This file contains the list of providers that needs to be loaded by the
+ * vendor's default AuthConfigFactory
+ */
+ providerConfigurationEntriesCollection = readProviderConfigurationXMLFile();
+
+ ProviderConfigurationEntry pce = null;
+
+ printVerticalIndent();
+ Iterator iterator = providerConfigurationEntriesCollection.iterator();
+ while (iterator.hasNext()) {
+ // obtain each ProviderConfigurationEntry and register it
+ // with vendor's default AuthConfigFactory
+ pce = iterator.next();
+
+ if (pce != null) {
+ logger.info("Registering Provider " + pce.getProviderClassName() + " ...");
+ systemAuthConfigFactory.registerConfigProvider(
+ pce.getProviderClassName(),
+ pce.getProperties(),
+ pce.getMessageLayer(),
+ pce.getApplicationContextId(),
+ pce.getRegistrationDescription());
+
+ logger.info("Registration Successful");
+ }
+ }
+
+ printVerticalIndent();
+
+ // Check whether the providers are registered for the right message layer
+ // and appContext
+ // verifyRegistrations(acf);
+
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory";
+ msg = msg + "or ACF.setFactory(). Check your server side security policies.";
+ logger.info(msg);
+ ex.printStackTrace();
+
+ } catch (Exception e) {
+ logger.info("Error Registering TestSuite AuthConfig Providers");
+ e.printStackTrace();
+ }
+
+ return true;
+
+ }
+
+ /**
+ * @keywords: jaspic_soap
+ *
+ * @testName: AuthConfigFactoryVerifyPersistence
+ *
+ * @assertion_ids: JASPIC:JAVADOC:75
+ *
+ * @test_Strategy: 1. Get System properties log.file.location, provider.configuration.file and vendor.authconfig.factory
+ *
+ * 2. Load vendor's AuthConfigFactory and make sure the registered providers return properly for the right message layer
+ * and appContextId
+ *
+ * Note: We test the persistance behaviour for vendor's AuthConfigFactory by registering providers from a persisted
+ * file, then we verify the registrations went correctly.
+ *
+ * Description
+ *
+ *
+ */
+ public void AuthConfigFactoryVerifyPersistence() {
+ try {
+
+ // register providers in vendor factory
+ assertTrue(register(logFileLocation, providerConfigFileLocation, vendorACFClass));
+
+ // Get system default AuthConfigFactory
+ AuthConfigFactory acf = AuthConfigFactory.getFactory();
+
+ if (acf != null) {
+ logger.info("Default AuthConfigFactory class name = " + acf.getClass().getName());
+
+ assertTrue(verifyRegistrations(acf));
+
+ } else {
+ logger.severe("Default AuthConfigFactory is null" + " can't verify registrations for TestSuite Providers");
+ }
+ } catch (SecurityException ex) {
+ // if here we may not have permission to invoke ACF.getFactory...
+ String msg = "SecurityException: make sure you have permission to call ACF.getFactory.";
+ msg = msg + " Check your server side security policies.";
+ logger.info(msg);
+ ex.printStackTrace();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @keywords: jaspic_soap
+ *
+ * @testName: AuthConfigFactorySetFactory
+ *
+ * @assertion_ids: JASPIC:SPEC:7; JASPIC:SPEC:10; JASPIC:JAVADOC:87; JASPIC:JAVADOC:80
+ *
+ * @test_Strategy: 1. Use the static setFactory method to set an ACF and this should always work.
+ *
+ * Description This method uses the getFactory() method to get the current factory, then it uses the setFactory() to
+ * change the current ACF. This method then verifies that the ACF's were indeed changed. We know that the setFactory()
+ * works as it is used in the bootstrap process - but this is an additional level of testing that allows us to set the
+ * factory in a slightly different manner than the bootstrap (eg reading it out of the java.security file.
+ */
+ @Test
+ public void AuthConfigFactorySetFactory() {
+ // Get current AuthConfigFactory
+ AuthConfigFactory currentAcf = AuthConfigFactory.getFactory();
+
+ assertNotNull(
+ "FAILURE - Could not get current AuthConfigFactory.",
+ currentAcf);
+
+ String currentACFClass = currentAcf.getClass().getName();
+ logger.info("currentACFClass = " + currentACFClass);
+
+ // Set our ACF to a new/different AuthConfigFactory
+ TSAuthConfigFactoryForStandalone newAcf = new TSAuthConfigFactoryForStandalone();
+ AuthConfigFactory.setFactory(newAcf);
+ String newACFClass = newAcf.getClass().getName();
+ logger.info("newACFClass = " + newACFClass);
+
+ // Verify our calls to getFactory() are getting the newly set factory
+ // instance and not the original ACF instance
+ AuthConfigFactory testAcf = AuthConfigFactory.getFactory();
+
+ assertNotNull(
+ "FAILURE - Could not get newly set AuthConfigFactory.",
+ testAcf);
+
+ String newlySetACFClass = testAcf.getClass().getName();
+ logger.info("newlySetACFClass = " + newlySetACFClass);
+
+ assertEquals(
+ "FAILURE - our current ACF does not match our newly set ACF",
+ newACFClass, newlySetACFClass);
+
+ logger.info("newlySetACFClass == newACFClass == " + newACFClass);
+
+ // Restore original factory class
+ AuthConfigFactory.setFactory(currentAcf);
+
+ logger.info("AuthConfigFactorySetFactory : PASSED");
+ }
+
+
+
+ private void printVerticalIndent() {
+ logger.info("**********************************************************");
+ logger.info("\n");
+ }
+
+ /**
+ * This method instantiates and returns a AuthConfigFactory based on the specified className
+ */
+ private AuthConfigFactory getVendorAuthConfigFactory(String className) {
+ AuthConfigFactory vFactory = null;
+
+ if (className != null) {
+ try {
+ vFactory = (AuthConfigFactory)
+ Class.forName(className, true, Thread.currentThread()
+ .getContextClassLoader())
+ .getDeclaredConstructor()
+ .newInstance();
+ logger.info("Instantiated Vendor's AuthConfigFactory");
+
+ } catch (Exception e) {
+ logger.info("Error instantiating vendor's " + "AuthConfigFactory class :" + className);
+ e.printStackTrace();
+
+ }
+ }
+
+ return vFactory;
+ }
+
+ /*
+ * Read the provider configuration XML file and registers each provider with Vendor's default AuthConfigFactory
+ */
+ private Collection readProviderConfigurationXMLFile() {
+ Collection providerConfigurationEntriesCollection = null;
+
+ logger.info("Reading TestSuite Providers from :" + providerConfigFileLocation);
+ try {
+ // Given the provider configuration xml file
+ // This reader parses the xml file and stores the configuration
+ // entries as a collection.
+ configFileProcessor = new ProviderConfigurationXMLFileProcessor(providerConfigFileLocation);
+
+ // Retrieve the ProviderConfigurationEntries collection
+ providerConfigurationEntriesCollection = configFileProcessor.getProviderConfigurationEntriesCollection();
+
+ logger.info("TestSuite Providers read successfully " + "from ProviderConfiguration.xml file");
+
+ return providerConfigurationEntriesCollection;
+
+ } catch (Exception e) {
+ logger.info("Error loading Providers");
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private boolean verifyRegistrations(AuthConfigFactory acf) {
+ logger.info("Verifying Provider Registrations ...");
+
+ try {
+ // Create a Registration listener
+ RegistrationListener rlis = new TSRegistrationListener();
+
+ // Get AuthConfigProvider for soap layer
+ AuthConfigProvider acp = acf.getConfigProvider(JASPICData.LAYER_SOAP, soapAppContext, rlis);
+
+ if (acp != null) {
+ if (acp.getClass().getName().equals("com.sun.ts.tests.jaspic.tssv.config.TSAuthConfigProvider")) {
+ logger.info("TSAuthConfigProvider registered for" + " message layer=SOAP" + " and appContextId=" + soapAppContext);
+ } else {
+ logger.info("Wrong provider registerd for " + " message layer=SOAP" + " and appContextId=" + soapAppContext);
+ return false;
+
+ }
+
+ } else {
+ logger.info(
+ "Error : No AuthConfigprovider registerd for" + " message layer=SOAP" + " and appContextId=" + soapAppContext);
+ return false;
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return true;
+
+ }
+}