Add TLS client auth rule.
authorScott Cantor <cantor.2@osu.edu>
Thu, 9 Nov 2006 05:44:14 +0000 (05:44 +0000)
committerScott Cantor <cantor.2@osu.edu>
Thu, 9 Nov 2006 05:44:14 +0000 (05:44 +0000)
saml/Makefile.am
saml/binding/ClientCertAuthRule.h [new file with mode: 0644]
saml/binding/SecurityPolicyRule.h
saml/binding/SimpleSigningRule.h
saml/binding/XMLSigningRule.h
saml/binding/impl/ClientCertAuthRule.cpp [new file with mode: 0644]
saml/binding/impl/SecurityPolicy.cpp
saml/binding/impl/SimpleSigningRule.cpp
saml/binding/impl/XMLSigningRule.cpp
saml/saml.vcproj

index e840ce5..f03cc16 100644 (file)
@@ -33,6 +33,7 @@ libsamlinclude_HEADERS = \
 
 samlbindinclude_HEADERS = \
        binding/ArtifactMap.h \
+       binding/ClientCertAuthRule.h \
        binding/GenericRequest.h \
        binding/GenericResponse.h \
        binding/HTTPRequest.h \
@@ -106,6 +107,7 @@ noinst_HEADERS = \
 libsaml_la_SOURCES = \
        SAMLConfig.cpp \
        binding/impl/ArtifactMap.cpp \
+       binding/impl/ClientCertAuthRule.cpp \
        binding/impl/MessageDecoder.cpp \
        binding/impl/MessageEncoder.cpp \
        binding/impl/MessageFlowRule.cpp \
diff --git a/saml/binding/ClientCertAuthRule.h b/saml/binding/ClientCertAuthRule.h
new file mode 100644 (file)
index 0000000..287f0e4
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file saml/binding/ClientCertAuthRule.h
+ * 
+ * TLS client authentication SecurityPolicyRule
+ */
+
+#include <saml/binding/SecurityPolicyRule.h>
+
+
+namespace opensaml {
+    /**
+     * TLS client authentication SecurityPolicyRule
+     */
+    class SAML_API ClientCertAuthRule : public SecurityPolicyRule
+    {
+    public:
+        ClientCertAuthRule(const DOMElement* e) {}
+        virtual ~ClientCertAuthRule() {}
+        
+        std::pair<saml2::Issuer*,const saml2md::RoleDescriptor*> evaluate(
+            const GenericRequest& request,
+            const xmltooling::XMLObject& message,
+            const saml2md::MetadataProvider* metadataProvider,
+            const xmltooling::QName* role,
+            const TrustEngine* trustEngine,
+            const MessageExtractor& extractor
+            ) const;
+    };
+    
+};
index 9a1b49f..14e0352 100644 (file)
@@ -103,6 +103,14 @@ namespace opensaml {
     void SAML_API registerSecurityPolicyRules();
 
     /**
+     * SecurityPolicyRule for TLS client certificate authentication.
+     * 
+     * Requires that messages carry information about the issuer, and then
+     * evaluates the claimed certificates against the issuer's metadata.
+     */
+    #define CLIENTCERTAUTH_POLICY_RULE  "org.opensaml.binding.ClientCertAuthRule"
+
+    /**
      * SecurityPolicyRule for replay detection and freshness checking.
      * 
      * <p>A ReplayCache instance must be available from the runtime, unless
index a4d79e2..e0488c0 100644 (file)
@@ -27,9 +27,6 @@ namespace opensaml {
     /**
      * Blob-oriented signature checking SecurityPolicyRule for
      * bindings that support non-XML signature techniques.
-     * 
-     * Subclasses can provide support for additional message types
-     * by overriding the issuer derivation method.
      */
     class SAML_API SimpleSigningRule : public SecurityPolicyRule
     {
index 29816b7..2b01d39 100644 (file)
@@ -26,9 +26,6 @@
 namespace opensaml {
     /**
      * XML Signature checking SecurityPolicyRule
-     * 
-     * Subclasses can provide support for additional message types
-     * by overriding the issuer derivation method.
      */
     class SAML_API XMLSigningRule : public SecurityPolicyRule
     {
diff --git a/saml/binding/impl/ClientCertAuthRule.cpp b/saml/binding/impl/ClientCertAuthRule.cpp
new file mode 100644 (file)
index 0000000..63a6bb1
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * ClientCertAuthRule.cpp
+ * 
+ * XML Signature checking SecurityPolicyRule
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "binding/ClientCertAuthRule.h"
+#include "saml2/metadata/Metadata.h"
+#include "saml2/metadata/MetadataProvider.h"
+#include "security/X509TrustEngine.h"
+
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/ReplayCache.h>
+#include <log4cpp/Category.hh>
+
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+namespace opensaml {
+    SecurityPolicyRule* SAML_DLLLOCAL ClientCertAuthRuleFactory(const DOMElement* const & e)
+    {
+        return new ClientCertAuthRule(e);
+    }
+};
+
+pair<saml2::Issuer*,const RoleDescriptor*> ClientCertAuthRule::evaluate(
+    const GenericRequest& request,
+    const XMLObject& message,
+    const MetadataProvider* metadataProvider,
+    const QName* role,
+    const opensaml::TrustEngine* trustEngine,
+    const MessageExtractor& extractor
+    ) const
+{
+    Category& log=Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.ClientCertAuth");
+    log.debug("evaluating client certificate authentication policy");
+    
+    pair<saml2::Issuer*,const RoleDescriptor*> ret = pair<saml2::Issuer*,const RoleDescriptor*>(NULL,NULL);  
+    
+    const opensaml::X509TrustEngine* x509trust;
+    if (!metadataProvider || !role || !(x509trust=dynamic_cast<const opensaml::X509TrustEngine*>(trustEngine))) {
+        log.debug("ignoring message, no metadata or X509TrustEngine supplied");
+        return ret;
+    }
+    
+    const std::vector<XSECCryptoX509*>& chain = request.getClientCertificates();
+    if (chain.empty()) {
+        log.debug("ignoring message, no client certificates in request");
+        return ret;
+    }
+    
+    try {
+        log.debug("extracting issuer from message");
+        pair<saml2::Issuer*,const XMLCh*> issuerInfo = extractor.getIssuerAndProtocol(message);
+        
+        auto_ptr<saml2::Issuer> issuer(issuerInfo.first);
+        if (!issuerInfo.first || !issuerInfo.second ||
+                (issuer->getFormat() && !XMLString::equals(issuer->getFormat(), saml2::NameIDType::ENTITY))) {
+            log.warn("issuer identity not estabished, or was not an entityID");
+            return ret;
+        }
+        
+        log.debug("searching metadata for message issuer...");
+        const EntityDescriptor* entity = metadataProvider->getEntityDescriptor(issuer->getName());
+        if (!entity) {
+            auto_ptr_char temp(issuer->getName());
+            log.warn("no metadata found, can't establish identity of issuer (%s)", temp.get());
+            return ret;
+        }
+
+        log.debug("matched message issuer against metadata, searching for applicable role...");
+        const RoleDescriptor* roledesc=entity->getRoleDescriptor(*role, issuerInfo.second);
+        if (!roledesc) {
+            log.warn("unable to find compatible role (%s) in metadata", role->toString().c_str());
+            return ret;
+        }
+
+        if (!x509trust->validate(chain.front(), chain, *roledesc, true, metadataProvider->getKeyResolver())) {
+            log.error("unable to verify certificate chain with supplied trust engine");
+            return ret;
+        }
+
+        if (log.isDebugEnabled()) {
+            auto_ptr_char iname(entity->getEntityID());
+            log.debug("message from (%s), signature verified", iname.get());
+        }
+        
+        ret.first = issuer.release();
+        ret.second = roledesc;
+    }
+    catch (bad_cast&) {
+        // Just trap it.
+        log.warn("caught a bad_cast while extracting issuer");
+    }
+    return ret;
+}
index 2edad23..89aad2d 100644 (file)
@@ -35,6 +35,7 @@ using namespace xmltooling;
 using namespace std;
 
 namespace opensaml {
+    SAML_DLLLOCAL PluginManager<SecurityPolicyRule,const DOMElement*>::Factory ClientCertAuthRuleFactory;
     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,const DOMElement*>::Factory MessageFlowRuleFactory;
     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,const DOMElement*>::Factory SimpleSigningRuleFactory;
     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,const DOMElement*>::Factory XMLSigningRuleFactory;
@@ -43,6 +44,7 @@ namespace opensaml {
 void SAML_API opensaml::registerSecurityPolicyRules()
 {
     SAMLConfig& conf=SAMLConfig::getConfig();
+    conf.SecurityPolicyRuleManager.registerFactory(CLIENTCERTAUTH_POLICY_RULE, ClientCertAuthRuleFactory);
     conf.SecurityPolicyRuleManager.registerFactory(MESSAGEFLOW_POLICY_RULE, MessageFlowRuleFactory);
     conf.SecurityPolicyRuleManager.registerFactory(SIMPLESIGNING_POLICY_RULE, SimpleSigningRuleFactory);
     conf.SecurityPolicyRuleManager.registerFactory(XMLSIGNING_POLICY_RULE, XMLSigningRuleFactory);
index 44c6e9c..6ba58f8 100644 (file)
 
 #include "internal.h"
 #include "exceptions.h"
-#include "RootObject.h"
 #include "binding/HTTPRequest.h"
 #include "binding/SimpleSigningRule.h"
-#include "saml2/core/Protocols.h"
 #include "saml2/metadata/Metadata.h"
 #include "saml2/metadata/MetadataProvider.h"
 #include "security/TrustEngine.h"
@@ -69,7 +67,7 @@ namespace opensaml {
 };
 
 
-pair<saml2::Issuer*,const saml2md::RoleDescriptor*> SimpleSigningRule::evaluate(
+pair<saml2::Issuer*,const RoleDescriptor*> SimpleSigningRule::evaluate(
     const GenericRequest& request,
     const XMLObject& message,
     const MetadataProvider* metadataProvider,
@@ -119,7 +117,7 @@ pair<saml2::Issuer*,const saml2md::RoleDescriptor*> SimpleSigningRule::evaluate(
             return ret;
         }
 
-        log.debug("matched assertion issuer against metadata, searching for applicable role...");
+        log.debug("matched message issuer against metadata, searching for applicable role...");
         const RoleDescriptor* roledesc=entity->getRoleDescriptor(*role, issuerInfo.second);
         if (!roledesc) {
             log.warn("unable to find compatible role (%s) in metadata", role->toString().c_str());
index a63c18c..552cef8 100644 (file)
@@ -22,9 +22,8 @@
 
 #include "internal.h"
 #include "exceptions.h"
-#include "RootObject.h"
 #include "binding/XMLSigningRule.h"
-#include "saml2/core/Protocols.h"
+#include "saml2/core/Assertions.h"
 #include "saml2/metadata/Metadata.h"
 #include "saml2/metadata/MetadataProvider.h"
 #include "security/TrustEngine.h"
@@ -46,7 +45,7 @@ namespace opensaml {
     }
 };
 
-pair<saml2::Issuer*,const saml2md::RoleDescriptor*> XMLSigningRule::evaluate(
+pair<saml2::Issuer*,const RoleDescriptor*> XMLSigningRule::evaluate(
     const GenericRequest& request,
     const XMLObject& message,
     const MetadataProvider* metadataProvider,
@@ -90,7 +89,7 @@ pair<saml2::Issuer*,const saml2md::RoleDescriptor*> XMLSigningRule::evaluate(
             return ret;
         }
 
-        log.debug("matched assertion issuer against metadata, searching for applicable role...");
+        log.debug("matched message issuer against metadata, searching for applicable role...");
         const RoleDescriptor* roledesc=entity->getRoleDescriptor(*role, issuerInfo.second);
         if (!roledesc) {
             log.warn("unable to find compatible role (%s) in metadata", role->toString().c_str());
index d6ca290..2a461bf 100644 (file)
                                                >\r
                                        </File>\r
                                        <File\r
+                                               RelativePath=".\binding\impl\ClientCertAuthRule.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
                                                RelativePath=".\binding\impl\MessageDecoder.cpp"\r
                                                >\r
                                        </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\binding\ClientCertAuthRule.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\binding\GenericRequest.h"\r
                                        >\r
                                </File>\r