[java-opensaml] 02/16: Work on SOAP client security and SAML 2 artifact decoder.
Brent Putman
putmanb at georgetown.edu
Fri Sep 21 22:48:40 EDT 2018
This is an automated email from the git hooks/post-receive script.
putmanb pushed a commit to branch master
in repository java-opensaml.
View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=02a67e6d7d489587d69b84cc080ef97405b76e18
commit 02a67e6d7d489587d69b84cc080ef97405b76e18
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Thu May 17 18:23:08 2018 -0400
Work on SOAP client security and SAML 2 artifact decoder.
---
.../soap/SAMLSOAPClientContextBuilder.java | 61 ++++++++++++++++-
.../binding/decoding/impl/HTTPArtifactDecoder.java | 51 +++++++++++++++
.../HttpClientSecurityConfigurationInitalizer.java | 37 +++++++++++
.../services/org.opensaml.core.config.Initializer | 3 +-
.../opensaml/soap/client/SOAPClientContext.java | 28 +++++++-
.../client/http/PipelineFactoryHttpSOAPClient.java | 35 ++++++++--
.../SOAPClientSecurityContext.java} | 37 ++++++-----
.../SOAPClientSecurityProfileIdLookupFunction.java | 76 ++++++++++++++++++++++
.../soap/client/security/package-info.java | 19 ++++++
9 files changed, 322 insertions(+), 25 deletions(-)
diff --git a/opensaml-saml-api/src/main/java/org/opensaml/saml/common/messaging/soap/SAMLSOAPClientContextBuilder.java b/opensaml-saml-api/src/main/java/org/opensaml/saml/common/messaging/soap/SAMLSOAPClientContextBuilder.java
index 188893c..1b182e8 100644
--- a/opensaml-saml-api/src/main/java/org/opensaml/saml/common/messaging/soap/SAMLSOAPClientContextBuilder.java
+++ b/opensaml-saml-api/src/main/java/org/opensaml/saml/common/messaging/soap/SAMLSOAPClientContextBuilder.java
@@ -41,9 +41,12 @@ import org.opensaml.saml.saml2.metadata.RoleDescriptor;
import org.opensaml.security.credential.UsageType;
import org.opensaml.security.criteria.UsageCriterion;
import org.opensaml.security.messaging.HttpClientSecurityContext;
+import org.opensaml.soap.client.SOAPClientContext;
+import org.opensaml.soap.client.security.SOAPClientSecurityContext;
import com.google.common.base.Function;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
//TODO when impl finished, document required vs optional data and derivation rules
@@ -78,6 +81,12 @@ public class SAMLSOAPClientContextBuilder<InboundMessageType extends SAMLObject,
/** TLS CriteriaSet strategy. */
private Function<MessageContext<?>, CriteriaSet> tlsCriteriaSetStrategy;
+ /** SOAP client message pipeline name. */
+ private String pipelineName;
+
+ /** SOAP client security configuration profile ID. */
+ private String securityConfigurationProfileId;
+
/**
* Get the outbound message.
*
@@ -231,7 +240,7 @@ public class SAMLSOAPClientContextBuilder<InboundMessageType extends SAMLObject,
/**
* Get the TLS CriteriaSet strategy.
*
- * @return Returns the tlsCriteriaSetStrategy.
+ * @return the TLS CriteriaSet strategy, or null
*/
@Nullable public Function<MessageContext<?>, CriteriaSet> getTLSCriteriaSetStrategy() {
if (tlsCriteriaSetStrategy != null) {
@@ -254,6 +263,48 @@ public class SAMLSOAPClientContextBuilder<InboundMessageType extends SAMLObject,
}
/**
+ * Get the SOAP client message pipeline name to use.
+ *
+ * @return the pipeline name, or null
+ */
+ @Nullable public String getPipelineName() {
+ return pipelineName;
+ }
+
+ /**
+ * Set the SOAP client message pipeline name to use.
+ *
+ * @param name the pipeline name, or null
+ * @return this builder instance
+ */
+ @Nonnull public SAMLSOAPClientContextBuilder<InboundMessageType, OutboundMessageType>
+ setPipelineName(@Nullable final String name) {
+ pipelineName = StringSupport.trimOrNull(name);
+ return this;
+ }
+
+ /**
+ * Get the SOAP client security configuration profile ID to use.
+ *
+ * @return the client security configuration profile ID, or null
+ */
+ @Nullable public String getSecurityConfigurationProfileId() {
+ return securityConfigurationProfileId;
+ }
+
+ /**
+ * Set the SOAP client security configuration profile ID to use.
+ *
+ * @param profileID the profile ID, or null
+ * @return this builder instance
+ */
+ @Nonnull public SAMLSOAPClientContextBuilder<InboundMessageType, OutboundMessageType>
+ setSecurityConfigurationProfileId(@Nullable final String profileId) {
+ securityConfigurationProfileId = StringSupport.trimOrNull(profileId);
+ return this;
+ }
+
+ /**
* Build the new operation context.
*
* @return the operation context
@@ -279,6 +330,14 @@ public class SAMLSOAPClientContextBuilder<InboundMessageType extends SAMLObject,
// This is just so it's easy to change.
final BaseContext parent = opContext;
+ if (getPipelineName() != null) {
+ parent.getSubcontext(SOAPClientContext.class, true).setPipelineName(getPipelineName());
+ }
+
+ if (getSecurityConfigurationProfileId() != null) {
+ parent.getSubcontext(SOAPClientSecurityContext.class, true).setSecurityConfigurationProfileId(getSecurityConfigurationProfileId());
+ }
+
//TODO is this required always?
final String selfID = getSelfEntityID();
if (selfID != null) {
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/binding/decoding/impl/HTTPArtifactDecoder.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/binding/decoding/impl/HTTPArtifactDecoder.java
index fb21fb6..a7c6b25 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/binding/decoding/impl/HTTPArtifactDecoder.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/binding/decoding/impl/HTTPArtifactDecoder.java
@@ -59,6 +59,7 @@ import org.opensaml.saml.saml2.metadata.ArtifactResolutionService;
import org.opensaml.saml.saml2.metadata.RoleDescriptor;
import org.opensaml.security.SecurityException;
import org.opensaml.soap.client.SOAPClient;
+import org.opensaml.soap.client.http.PipelineFactoryHttpSOAPClient;
import org.opensaml.soap.common.SOAPException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -105,6 +106,12 @@ public class HTTPArtifactDecoder extends BaseHttpServletRequestXMLMessageDecoder
/** SOAP client. */
private SOAPClient soapClient;
+ /** The SOAP client message pipeline name. */
+ private String soapPipelineName;
+
+ /** SOAP client security configuration profile ID. */
+ private String soapClientSecurityConfigurationProfileId;
+
/** Identifier generation strategy. */
private IdentifierGenerationStrategy idStrategy;
@@ -305,6 +312,47 @@ public class HTTPArtifactDecoder extends BaseHttpServletRequestXMLMessageDecoder
ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
soapClient = client;
}
+
+ /**
+ * Get the name of the specific SOAP client message pipeline to use,
+ * for example with {@link PipelineFactoryHttpSOAPClient}.
+ *
+ * @return the pipeline name, or null
+ */
+ @Nullable public String getSOAPPipelineName() {
+ return soapPipelineName;
+ }
+
+ /**
+ * Set the name of the specific SOAP client message pipeline to use,
+ * for example with {@link PipelineFactoryHttpSOAPClient}.
+ *
+ * @param name the pipeline name, or null
+ */
+ public void setSOAPPipelineName(@Nullable final String name) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+ soapPipelineName = StringSupport.trimOrNull(name);
+ }
+
+ /**
+ * Get the SOAP client security configuration profile ID to use.
+ *
+ * @return the client security configuration profile ID, or null
+ */
+ @Nullable public String getSOAPClientSecurityConfigurationProfileId() {
+ return soapClientSecurityConfigurationProfileId;
+ }
+
+ /**
+ * Set the SOAP client security configuration profile ID to use.
+ *
+ * @param profileID the profile ID, or null
+ * @return this builder instance
+ */
+ @Nonnull public void setSOAPClientSecurityConfigurationProfileId(@Nullable final String profileId) {
+ soapClientSecurityConfigurationProfileId = StringSupport.trimOrNull(profileId);
+ }
/** {@inheritDoc} */
@Nonnull @NotEmpty public String getBindingURI() {
@@ -358,6 +406,7 @@ public class HTTPArtifactDecoder extends BaseHttpServletRequestXMLMessageDecoder
*/
private void processArtifact(final MessageContext messageContext, final HttpServletRequest request)
throws MessageDecodingException {
+
final String encodedArtifact = StringSupport.trimOrNull(request.getParameter("SAMLart"));
if (encodedArtifact == null) {
log.error("URL SAMLart parameter was missing or did not contain a value.");
@@ -404,6 +453,8 @@ public class HTTPArtifactDecoder extends BaseHttpServletRequestXMLMessageDecoder
final InOutOperationContext<SAMLObject, ArtifactResolve> opContext = new SAMLSOAPClientContextBuilder()
.setOutboundMessage(buildArtifactResolveRequestMessage(
artifact, ars.getLocation(), peerRoleDescriptor, selfEntityID))
+ .setPipelineName(getSOAPPipelineName())
+ .setSecurityConfigurationProfileId(getSOAPClientSecurityConfigurationProfileId())
.setPeerRoleDescriptor(peerRoleDescriptor)
.setSelfEntityID(selfEntityID)
.build();
diff --git a/opensaml-security-impl/src/main/java/org/opensaml/security/config/impl/HttpClientSecurityConfigurationInitalizer.java b/opensaml-security-impl/src/main/java/org/opensaml/security/config/impl/HttpClientSecurityConfigurationInitalizer.java
new file mode 100644
index 0000000..d08ddc8
--- /dev/null
+++ b/opensaml-security-impl/src/main/java/org/opensaml/security/config/impl/HttpClientSecurityConfigurationInitalizer.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opensaml.security.config.impl;
+
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.core.config.InitializationException;
+import org.opensaml.core.config.Initializer;
+import org.opensaml.security.httpclient.HttpClientSecurityConfiguration;
+import org.opensaml.security.httpclient.impl.BasicHttpClientSecurityConfiguration;
+
+/**
+ * An initializer which initializes the global {@link HttpClientSecurityConfiguration}.
+ */
+public class HttpClientSecurityConfigurationInitalizer implements Initializer {
+
+ /** {@inheritDoc} */
+ public void init() throws InitializationException {
+ // This is empty, just need to register it to satisfy resolver in case no others are supplied.
+ ConfigurationService.register(HttpClientSecurityConfiguration.class, new BasicHttpClientSecurityConfiguration());
+ }
+
+}
diff --git a/opensaml-security-impl/src/main/resources/META-INF/services/org.opensaml.core.config.Initializer b/opensaml-security-impl/src/main/resources/META-INF/services/org.opensaml.core.config.Initializer
index 3a2a150..9492c80 100644
--- a/opensaml-security-impl/src/main/resources/META-INF/services/org.opensaml.core.config.Initializer
+++ b/opensaml-security-impl/src/main/resources/META-INF/services/org.opensaml.core.config.Initializer
@@ -1 +1,2 @@
-org.opensaml.security.config.impl.ClientTLSValidationConfiguratonInitializer
\ No newline at end of file
+org.opensaml.security.config.impl.ClientTLSValidationConfiguratonInitializer
+org.opensaml.security.config.impl.HttpClientSecurityConfigurationInitalizer
\ No newline at end of file
diff --git a/opensaml-soap-api/src/main/java/org/opensaml/soap/client/SOAPClientContext.java b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/SOAPClientContext.java
index 757037a..c8fb849 100644
--- a/opensaml-soap-api/src/main/java/org/opensaml/soap/client/SOAPClientContext.java
+++ b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/SOAPClientContext.java
@@ -21,12 +21,18 @@ import javax.annotation.Nullable;
import org.opensaml.messaging.context.BaseContext;
import org.opensaml.soap.client.SOAPClient.SOAPRequestParameters;
+import org.opensaml.soap.client.http.PipelineFactoryHttpSOAPClient;
+
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
/** Message context for SOAP client messages. */
public class SOAPClientContext extends BaseContext {
/** Binding/transport-specific SOAP request parameters. */
- private SOAPRequestParameters requestParameters;
+ @Nullable private SOAPRequestParameters requestParameters;
+
+ /** Name of the specific SOAP client pipeline to use, for example with {@link PipelineFactoryHttpSOAPClient}. */
+ @Nullable private String pipelineName;
/**
* Gets a set of binding/transport-specific request parameters.
@@ -46,4 +52,24 @@ public class SOAPClientContext extends BaseContext {
requestParameters = parameters;
}
+ /**
+ * Get the name of the specific SOAP client message pipeline to use,
+ * for example with {@link PipelineFactoryHttpSOAPClient}.
+ *
+ * @return the pipeline name, or null
+ */
+ @Nullable public String getPipelineName() {
+ return pipelineName;
+ }
+
+ /**
+ * Set the name of the specific SOAP client message pipeline to use,
+ * for example with {@link PipelineFactoryHttpSOAPClient}.
+ *
+ * @param name the pipeline name, or null
+ */
+ public void setPipelineName(@Nullable final String name) {
+ pipelineName = StringSupport.trimOrNull(name);
+ }
+
}
\ No newline at end of file
diff --git a/opensaml-soap-api/src/main/java/org/opensaml/soap/client/http/PipelineFactoryHttpSOAPClient.java b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/http/PipelineFactoryHttpSOAPClient.java
index 96d2904..a511d87 100644
--- a/opensaml-soap-api/src/main/java/org/opensaml/soap/client/http/PipelineFactoryHttpSOAPClient.java
+++ b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/http/PipelineFactoryHttpSOAPClient.java
@@ -21,19 +21,20 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-
import org.opensaml.messaging.context.InOutOperationContext;
import org.opensaml.messaging.pipeline.httpclient.HttpClientMessagePipeline;
import org.opensaml.messaging.pipeline.httpclient.HttpClientMessagePipelineFactory;
+import org.opensaml.soap.client.SOAPClientContext;
import org.opensaml.soap.common.SOAPException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
/**
* SOAP client that is based on {@link HttpClientMessagePipeline}, produced at runtime from an instance of
* {@link HttpClientMessagePipelineFactory}.
@@ -86,6 +87,10 @@ public class PipelineFactoryHttpSOAPClient<OutboundMessageType, InboundMessageTy
if (pipelineFactory == null) {
throw new ComponentInitializationException("HttpClientPipelineFactory cannot be null");
}
+
+ if (pipelineNameStrategy == null) {
+ pipelineNameStrategy = new DefaultPipelineNameStrategy();
+ }
}
/** {@inheritDoc} */
@@ -189,5 +194,27 @@ public class PipelineFactoryHttpSOAPClient<OutboundMessageType, InboundMessageTy
return null;
}
}
+
+
+ /**
+ * Default strategy for resolving SOAP client message pipeline name from the
+ * {@link SOAPClientContext#getPipelineName()} which is a direct child of the input operation context.
+ */
+ public static class DefaultPipelineNameStrategy implements Function<InOutOperationContext<?,?>, String> {
+
+ /** {@inheritDoc} */
+ public String apply(@Nullable final InOutOperationContext<?, ?> opContext) {
+ if (opContext == null) {
+ return null;
+ }
+ final SOAPClientContext context = opContext.getSubcontext(SOAPClientContext.class);
+ if (context != null) {
+ return context.getPipelineName();
+ } else {
+ return null;
+ }
+ }
+
+ }
}
diff --git a/opensaml-soap-api/src/main/java/org/opensaml/soap/client/SOAPClientContext.java b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/security/SOAPClientSecurityContext.java
similarity index 53%
copy from opensaml-soap-api/src/main/java/org/opensaml/soap/client/SOAPClientContext.java
copy to opensaml-soap-api/src/main/java/org/opensaml/soap/client/security/SOAPClientSecurityContext.java
index 757037a..01013ba 100644
--- a/opensaml-soap-api/src/main/java/org/opensaml/soap/client/SOAPClientContext.java
+++ b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/security/SOAPClientSecurityContext.java
@@ -15,35 +15,36 @@
* limitations under the License.
*/
-package org.opensaml.soap.client;
+package org.opensaml.soap.client.security;
import javax.annotation.Nullable;
import org.opensaml.messaging.context.BaseContext;
-import org.opensaml.soap.client.SOAPClient.SOAPRequestParameters;
-/** Message context for SOAP client messages. */
-public class SOAPClientContext extends BaseContext {
-
- /** Binding/transport-specific SOAP request parameters. */
- private SOAPRequestParameters requestParameters;
+/**
+ * Context class for holding security information related to SOAP client operations.
+ */
+public class SOAPClientSecurityContext extends BaseContext {
+
+ /** Security configuration profile ID. */
+ @Nullable private String securityConfigurationProfileId;
/**
- * Gets a set of binding/transport-specific request parameters.
- *
- * @return set of binding/transport-specific request parameters
+ * Get the security configuration profile ID.
+ *
+ * @return the profile ID, or null
*/
- @Nullable public SOAPRequestParameters getSOAPRequestParameters() {
- return requestParameters;
+ @Nullable public String getSecurityConfigurationProfileId() {
+ return securityConfigurationProfileId;
}
/**
- * Sets a set of binding/transport-specific request parameters.
- *
- * @param parameters a set of binding/transport-specific request parameters
+ * Set the security configuration profile ID.
+ *
+ * @param profileId The profileID to set
*/
- public void setSOAPRequestParameters(@Nullable final SOAPRequestParameters parameters) {
- requestParameters = parameters;
+ public void setSecurityConfigurationProfileId(@Nullable final String profileId) {
+ securityConfigurationProfileId = profileId;
}
-}
\ No newline at end of file
+}
diff --git a/opensaml-soap-api/src/main/java/org/opensaml/soap/client/security/SOAPClientSecurityProfileIdLookupFunction.java b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/security/SOAPClientSecurityProfileIdLookupFunction.java
new file mode 100644
index 0000000..f30d1c1
--- /dev/null
+++ b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/security/SOAPClientSecurityProfileIdLookupFunction.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opensaml.soap.client.security;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.InOutOperationContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.ContextDataLookupFunction;
+import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Function to resolve SOAP client security profile ID from message context.
+ */
+public class SOAPClientSecurityProfileIdLookupFunction implements ContextDataLookupFunction<MessageContext, String> {
+
+ /** Lookup function for {@link SOAPClientSecurityContext. */
+ private Function<MessageContext, SOAPClientSecurityContext> soapContextLookup;
+
+ /**
+ * Constructor.
+ */
+ public SOAPClientSecurityProfileIdLookupFunction() {
+ soapContextLookup = Functions.compose(
+ new ChildContextLookup<>(SOAPClientSecurityContext.class),
+ new RecursiveTypedParentContextLookup(InOutOperationContext.class)
+ );
+ }
+
+ /**
+ * Set lookup function for for {@link SOAPClientSecurityContext}.
+ *
+ * @param lookup the lookup function
+ */
+ public void setSOAPClientSecurityContextLookup(
+ @Nonnull final Function<MessageContext, SOAPClientSecurityContext> lookup) {
+ soapContextLookup = Constraint.isNotNull(lookup, "SOAPClientSecurityContext lookup function was null") ;
+ }
+
+ /** {@inheritDoc} */
+ public String apply(@Nullable final MessageContext messageContext) {
+ if (messageContext == null) {
+ return null;
+ }
+
+ final SOAPClientSecurityContext context = soapContextLookup.apply(messageContext);
+ if (context != null) {
+ return context.getSecurityConfigurationProfileId();
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/opensaml-soap-api/src/main/java/org/opensaml/soap/client/security/package-info.java b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/security/package-info.java
new file mode 100644
index 0000000..d5e0b55
--- /dev/null
+++ b/opensaml-soap-api/src/main/java/org/opensaml/soap/client/security/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Classes related to SOAP client security. */
+package org.opensaml.soap.client.security;
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list