Revamped credential APIs.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Sat, 8 Nov 2003 07:25:20 +0000 (07:25 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Sat, 8 Nov 2003 07:25:20 +0000 (07:25 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@731 cb58f699-b61c-0410-a6fe-9272a202ed29

12 files changed:
shib/AAP.cpp
shib/Constants.cpp
shib/CredResolvers.cpp [new file with mode: 0644]
shib/Makefile.am
shib/ShibConfig.cpp
shib/XML.cpp
shib/XMLCredentials.cpp
shib/XMLMetadata.cpp
shib/XMLTrust.cpp
shib/internal.h
shib/shib.dsp
shib/shib.h

index f413cac..b7ba035 100644 (file)
@@ -68,66 +68,94 @@ using namespace std;
 #include <xercesc/framework/URLInputSource.hpp>
 #include <xercesc/util/regx/RegularExpression.hpp>
 
-class shibboleth::XMLAAPImpl
-{
-public:
-    XMLAAPImpl(const char* pathname);
-    ~XMLAAPImpl();
-    
-    void regAttributes() const;
+namespace shibboleth {
 
-    class AttributeRule : public IAttributeRule
+    class XMLAAPImpl
     {
     public:
-        AttributeRule(const DOMElement* e);
-        ~AttributeRule() {}
-        
-        const XMLCh* getName() const { return m_name; }
-        const XMLCh* getNamespace() const { return m_namespace; }
-        const char* getFactory() const { return m_factory.get(); }
-        const char* getAlias() const { return m_alias.get(); }
-        const char* getHeader() const { return m_header.get(); }
-        bool accept(const XMLCh* originSite, const DOMElement* e) const;
-
-        enum value_type { literal, regexp, xpath };
-    private:    
-        const XMLCh* m_name;
-        const XMLCh* m_namespace;
-        auto_ptr<char> m_factory;
-        auto_ptr<char> m_alias;
-        auto_ptr<char> m_header;
-        
-        value_type toValueType(const DOMElement* e);
-        bool scopeCheck(const XMLCh* originSite, const DOMElement* e) const;
+        XMLAAPImpl(const char* pathname);
+        ~XMLAAPImpl();
         
-        struct SiteRule
+        void regAttributes() const;
+    
+        class AttributeRule : public IAttributeRule
         {
-            SiteRule() : anyValue(false) {}
-            bool anyValue;
-            vector<pair<value_type,const XMLCh*> > valueRules;
-            vector<pair<value_type,const XMLCh*> > scopeDenials;
-            vector<pair<value_type,const XMLCh*> > scopeAccepts;
+        public:
+            AttributeRule(const DOMElement* e);
+            ~AttributeRule() {}
+            
+            const XMLCh* getName() const { return m_name; }
+            const XMLCh* getNamespace() const { return m_namespace; }
+            const char* getFactory() const { return m_factory.get(); }
+            const char* getAlias() const { return m_alias.get(); }
+            const char* getHeader() const { return m_header.get(); }
+            bool accept(const XMLCh* originSite, const DOMElement* e) const;
+    
+            enum value_type { literal, regexp, xpath };
+        private:    
+            const XMLCh* m_name;
+            const XMLCh* m_namespace;
+            auto_ptr<char> m_factory;
+            auto_ptr<char> m_alias;
+            auto_ptr<char> m_header;
+            
+            value_type toValueType(const DOMElement* e);
+            bool scopeCheck(const XMLCh* originSite, const DOMElement* e) const;
+            
+            struct SiteRule
+            {
+                SiteRule() : anyValue(false) {}
+                bool anyValue;
+                vector<pair<value_type,const XMLCh*> > valueRules;
+                vector<pair<value_type,const XMLCh*> > scopeDenials;
+                vector<pair<value_type,const XMLCh*> > scopeAccepts;
+            };
+    
+            SiteRule m_anySiteRule;
+    #ifdef HAVE_GOOD_STL
+            typedef map<xstring,SiteRule> sitemap_t;
+    #else
+            typedef map<string,SiteRule> sitemap_t;
+    #endif
+            sitemap_t m_siteMap;
         };
+    
+        vector<const IAttributeRule*> m_attrs;
+        map<string,const IAttributeRule*> m_aliasMap;
+    #ifdef HAVE_GOOD_STL
+        typedef map<xstring,AttributeRule*> attrmap_t;
+    #else
+        typedef map<string,AttributeRule*> attrmap_t;
+    #endif
+        attrmap_t m_attrMap;
+        DOMDocument* m_doc;
+    };
 
-        SiteRule m_anySiteRule;
-#ifdef HAVE_GOOD_STL
-        typedef map<xstring,SiteRule> sitemap_t;
-#else
-        typedef map<string,SiteRule> sitemap_t;
-#endif
-        sitemap_t m_siteMap;
+    class XMLAAP : public IAAP
+    {
+    public:
+        XMLAAP(const char* pathname);
+        ~XMLAAP() { delete m_lock; delete m_impl; }
+        
+        void lock();
+        void unlock() { m_lock->unlock(); }
+        const IAttributeRule* lookup(const XMLCh* attrName, const XMLCh* attrNamespace=NULL) const;
+        const IAttributeRule* lookup(const char* alias) const;
+        saml::Iterator<const IAttributeRule*> getAttributeRules() const;
+
+    private:
+        std::string m_source;
+        time_t m_filestamp;
+        RWLock* m_lock;
+        XMLAAPImpl* m_impl;
     };
 
-    vector<const IAttributeRule*> m_attrs;
-    map<string,const IAttributeRule*> m_aliasMap;
-#ifdef HAVE_GOOD_STL
-    typedef map<xstring,AttributeRule*> attrmap_t;
-#else
-    typedef map<string,AttributeRule*> attrmap_t;
-#endif
-    attrmap_t m_attrMap;
-    DOMDocument* m_doc;
-};
+}
+
+extern "C" IAAP* XMLAAPFactory(const char* source)
+{
+    return new XMLAAP(source);
+}
 
 XMLAAPImpl::XMLAAPImpl(const char* pathname) : m_doc(NULL)
 {
@@ -359,12 +387,6 @@ XMLAAP::XMLAAP(const char* pathname) : m_filestamp(0), m_source(pathname), m_imp
     m_lock=RWLock::create();
 }
 
-XMLAAP::~XMLAAP()
-{
-    delete m_lock;
-    delete m_impl;
-}
-
 void XMLAAP::lock()
 {
     m_lock->rdlock();
@@ -418,11 +440,6 @@ void XMLAAP::lock()
     }
 }
 
-void XMLAAP::unlock()
-{
-    m_lock->unlock();
-}
-
 const IAttributeRule* XMLAAP::lookup(const XMLCh* attrName, const XMLCh* attrNamespace) const
 {
 #ifdef HAVE_GOOD_STL
index b7a808c..b6d4d0d 100644 (file)
@@ -89,31 +89,4 @@ const XMLCh Constants::XMLSIG_RETMETHOD_RAWX509[] = // http://www.w3.org/2000/09
     chLatin_C, chLatin_e, chLatin_r, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_c, chLatin_a, chLatin_t, chLatin_e, chNull
 };
 
-const XMLCh Constants::SHIB_RETMETHOD_PEMX509[] = // urn:mace:shibboleth:1.0:xmldsig:pemX509Certificate
-{
-  chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
-  chDigit_1, chPeriod, chDigit_0, chColon, chLatin_x, chLatin_m, chLatin_l, chLatin_d, chLatin_s, chLatin_i, chLatin_g, chColon,
-  chLatin_p, chLatin_e, chLatin_m, chLatin_X, chDigit_5, chDigit_0, chDigit_9,
-    chLatin_C, chLatin_e, chLatin_r, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_c, chLatin_a, chLatin_t, chLatin_e, chNull
-};
-
-const XMLCh Constants::SHIB_RETMETHOD_DERRSA[] = // urn:mace:shibboleth:1.0:xmldsig:derRSAPrivateKey
-{
-  chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
-  chDigit_1, chPeriod, chDigit_0, chColon, chLatin_x, chLatin_m, chLatin_l, chLatin_d, chLatin_s, chLatin_i, chLatin_g, chColon,
-  chLatin_d, chLatin_e, chLatin_r, chLatin_R, chLatin_S, chLatin_A,
-    chLatin_P, chLatin_r, chLatin_i, chLatin_v, chLatin_a, chLatin_t, chLatin_e, chLatin_K, chLatin_e, chLatin_y, chNull
-};
-
-const XMLCh Constants::SHIB_RETMETHOD_PEMRSA[] = // urn:mace:shibboleth:1.0:xmldsig:pemRSAPrivateKey
-{
-  chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
-  chDigit_1, chPeriod, chDigit_0, chColon, chLatin_x, chLatin_m, chLatin_l, chLatin_d, chLatin_s, chLatin_i, chLatin_g, chColon,
-  chLatin_p, chLatin_e, chLatin_m, chLatin_R, chLatin_S, chLatin_A,
-    chLatin_P, chLatin_r, chLatin_i, chLatin_v, chLatin_a, chLatin_t, chLatin_e, chLatin_K, chLatin_e, chLatin_y, chNull
-};
-
 saml::QName Constants::SHIB_ATTRIBUTE_VALUE_TYPE(XML::SHIB_NS,XML::Literals::AttributeValueType);
diff --git a/shib/CredResolvers.cpp b/shib/CredResolvers.cpp
new file mode 100644 (file)
index 0000000..5eb9256
--- /dev/null
@@ -0,0 +1,335 @@
+/* 
+ * The Shibboleth License, Version 1. 
+ * Copyright (c) 2002 
+ * University Corporation for Advanced Internet Development, Inc. 
+ * All rights reserved
+ * 
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, this 
+ * list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation 
+ * and/or other materials provided with the distribution, if any, must include 
+ * the following acknowledgment: "This product includes software developed by 
+ * the University Corporation for Advanced Internet Development 
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
+ * may appear in the software itself, if and wherever such third-party 
+ * acknowledgments normally appear.
+ * 
+ * Neither the name of Shibboleth nor the names of its contributors, nor 
+ * Internet2, nor the University Corporation for Advanced Internet Development, 
+ * Inc., nor UCAID may be used to endorse or promote products derived from this 
+ * software without specific prior written permission. For written permission, 
+ * please contact shibboleth@shibboleth.org
+ * 
+ * Products derived from this software may not be called Shibboleth, Internet2, 
+ * UCAID, or the University Corporation for Advanced Internet Development, nor 
+ * may Shibboleth appear in their name, without prior written permission of the 
+ * University Corporation for Advanced Internet Development.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* CredResolvers.cpp - default implementations of the ICredResolver interface
+
+   Scott Cantor
+   9/27/02
+
+   $History:$
+*/
+
+#include "internal.h"
+
+#include <log4cpp/Category.hh>
+#include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
+
+using namespace shibboleth;
+using namespace log4cpp;
+using namespace std;
+
+// OpenSSL password callback...
+int passwd_callback(char* buf, int len, int verify, void* passwd)
+{
+    if(!verify)
+    {
+        if(passwd && len > strlen(reinterpret_cast<char*>(passwd)))
+        {
+            strcpy(buf,reinterpret_cast<char*>(passwd));
+            return strlen(buf);
+        }
+    }  
+    return 0;
+}
+
+// File-based resolver
+
+class FileResolver : public ICredResolver
+{
+public:
+    FileResolver(const DOMElement* e);
+    ~FileResolver() {}
+    virtual void resolveKey(SSL_CTX* ctx) const;
+    virtual void resolveCert(SSL_CTX* ctx) const;
+    virtual void dump(FILE* f) const;
+    
+protected:
+    enum format_t { DER=SSL_FILETYPE_ASN1, PEM=SSL_FILETYPE_PEM };
+    format_t m_format;
+    string m_path;
+    string m_password;
+};
+
+// ds:KeyInfo resolver, currently limited to X.509 certs
+
+class KeyInfoResolver : public ICredResolver
+{
+public:
+    KeyInfoResolver(const DOMElement* e);
+    ~KeyInfoResolver();
+    virtual void resolveKey(SSL_CTX* ctx) const;
+    virtual void resolveCert(SSL_CTX* ctx) const;
+    virtual void dump(FILE* f) const;
+    
+private:
+    vector<X509*> m_certs;
+};
+
+
+FileResolver::FileResolver(const DOMElement* e)
+{
+    static const XMLCh cPEM[] = { chLatin_P, chLatin_E, chLatin_M, chNull };
+    
+    const XMLCh* format=e->getAttributeNS(NULL,L(Format));
+    if (!format || !*format || !XMLString::compareString(format,cPEM))
+        m_format=PEM;
+    else
+        m_format=DER;
+        
+    const XMLCh* s=saml::XML::getFirstChildElement(e,XML::SHIB_NS,SHIB_L(Path))->getFirstChild()->getNodeValue();
+    auto_ptr<char> path(XMLString::transcode(s));
+    
+#ifdef WIN32
+    struct _stat stat_buf;
+    if (_stat(path.get(), &stat_buf) != 0)
+#else
+    struct stat stat_buf;
+    if (stat(path.get(), &stat_buf) != 0)
+#endif
+    {
+        saml::NDC ndc("FileResolver");
+        Category::getInstance(SHIB_LOGCAT".CredResolvers").error("credential file '%s' can't be opened", path.get());
+        throw MetadataException("FileResolver() can't access credential file");
+    }
+    m_path=path.get();
+
+    DOMElement* p=saml::XML::getFirstChildElement(e,XML::SHIB_NS,SHIB_L(Password));
+    if (p)
+    {
+        s=p->getFirstChild()->getNodeValue();
+        auto_ptr<char> pass(XMLString::transcode(s));
+        m_password=pass.get();
+    }
+}
+
+void FileResolver::resolveKey(SSL_CTX* ctx) const
+{
+    SSL_CTX_set_default_passwd_cb_userdata(ctx, const_cast<char*>(m_password.c_str()));
+    SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
+
+    int ret;
+    switch (m_format)
+    {
+        case PEM:
+            ret=SSL_CTX_use_PrivateKey_file(ctx, m_path.c_str(), m_format);
+            break;
+            
+        default:
+            ret=SSL_CTX_use_RSAPrivateKey_file(ctx, m_path.c_str(), m_format);
+    }
+    
+    if (ret!=1)
+    {
+        log_openssl();
+        throw MetadataException("FileResolver::resolveKey() unable to set private key from file");
+    }
+}
+
+void FileResolver::resolveCert(SSL_CTX* ctx) const
+{
+    SSL_CTX_set_default_passwd_cb_userdata(ctx, const_cast<char*>(m_password.c_str()));
+    SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
+
+    int ret;
+    switch (m_format)
+    {
+        case PEM:
+            ret=SSL_CTX_use_certificate_chain_file(ctx, m_path.c_str());
+            break;
+            
+        default:
+            ret=SSL_CTX_use_certificate_file(ctx, m_path.c_str(), m_format);
+    }
+    
+    if (ret!=1)
+    {
+        log_openssl();
+        throw MetadataException("FileResolver::resolveCert() unable to set certificate from file");
+    }
+}
+
+void FileResolver::dump(FILE* f) const
+{
+    RSA* rsa=NULL;
+    X509* x=NULL;
+    BIO* in=BIO_new(BIO_s_file_internal());
+    if (in && BIO_read_filename(in,m_path.c_str())>0)
+    {
+        if (m_format==DER)
+        {
+            rsa=d2i_RSAPrivateKey_bio(in,NULL);
+            if (!rsa)
+                x=d2i_X509_bio(in,NULL);
+        }
+        else
+        {
+            rsa=PEM_read_bio_RSAPrivateKey(in,NULL,passwd_callback,const_cast<char*>(m_password.c_str()));
+            if (!rsa)
+                x=PEM_read_bio_X509(in,NULL,passwd_callback,const_cast<char*>(m_password.c_str()));
+        }
+        if (rsa)
+        {
+            RSA_print_fp(f,rsa,0);
+            RSA_free(rsa);
+            BIO_free(in);
+            return;
+        }
+        else if (x)
+        {
+            X509_print_ex_fp(f,x,XN_FLAG_SEP_MULTILINE,0);
+            X509_free(x);
+            if (m_format==PEM)
+            {
+                while (x=PEM_read_bio_X509(in,NULL,passwd_callback,const_cast<char*>(m_password.c_str())))
+                {
+                    fprintf(f,"\n-------\n");
+                    X509_print_ex_fp(f,x,XN_FLAG_SEP_MULTILINE,0);
+                    X509_free(x);
+                }
+            }
+            BIO_free(in);
+            return;
+        }
+        if (in)
+            BIO_free(in);
+    }
+    fprintf(f,"ERROR while loading credential for printing\n");
+}
+
+KeyInfoResolver::KeyInfoResolver(const DOMElement* e)
+{
+    saml::NDC ndc("KeyInfoResolver");
+    Category& log=Category::getInstance(SHIB_LOGCAT".CredResolvers");
+    // Is there an X509Data?
+    DOMNodeList* x509data=e->getElementsByTagNameNS(saml::XML::XMLSIG_NS,L(X509Data));
+    if (x509data && x509data->getLength())
+    {
+        if (x509data->getLength()>1)
+            log.warn("Found multiple certificate chains, using the first");
+
+        // Grab up any X509Certificate elements.
+        DOMNodeList* certlist=static_cast<DOMElement*>(x509data->item(0))->getElementsByTagNameNS(
+            saml::XML::XMLSIG_NS,L(X509Certificate)
+            );
+        for (int i=0; certlist && i<certlist->getLength(); i++)
+        {
+            auto_ptr<char> blob(XMLString::transcode(certlist->item(i)->getFirstChild()->getNodeValue()));
+            X509* x=B64_to_X509(blob.get());
+            if (x)
+                m_certs.push_back(x);
+            else
+                log.warn("Unable to parse ds:X509Certificate element, can't include in chain");
+        }
+    }
+    
+    if (m_certs.size()==0)
+    {
+        log.error("found no inline certificates in a ds:X509Data element");
+        throw MetadataException("KeyInfoResolver() can't find inline certificates to use");
+    }
+}
+
+KeyInfoResolver::~KeyInfoResolver()
+{
+    for (vector<X509*>::iterator i=m_certs.begin(); i!=m_certs.end(); i++)
+        X509_free(*i);
+}
+
+void KeyInfoResolver::resolveKey(SSL_CTX* ctx) const
+{
+    throw MetadataException("KeyInfoResolver::resolveKey() cannot set private key based on ds:KeyInfo");
+}
+
+void KeyInfoResolver::resolveCert(SSL_CTX* ctx) const
+{
+    for (vector<X509*>::const_reverse_iterator i=m_certs.rbegin(); i!=m_certs.rend(); i++)
+    {
+        if (i==m_certs.rbegin())
+        {
+            if (SSL_CTX_use_certificate(ctx, *i) != 1)
+            {
+                log_openssl();
+                throw MetadataException("KeyInfoResolver::resolveCert() unable to set entity certificate from ds:KeyInfo");
+            }
+        }
+        else
+        {
+            // When we add extra certs, they don't get ref counted, so we need to duplicate them.
+            X509* dup = X509_dup(*i);
+            if (SSL_CTX_add_extra_chain_cert(ctx, dup) != 0)
+            {
+                X509_free(dup);
+                log_openssl();
+                throw MetadataException("KeyInfoResolver::resolveCert() unable to add CA certificate from ds:KeyInfo");
+            }
+        }
+    }
+}
+
+void KeyInfoResolver::dump(FILE* f) const
+{
+    for (vector<X509*>::const_reverse_iterator i=m_certs.rbegin(); i!=m_certs.rend(); i++)
+    {
+        if (i!=m_certs.rbegin())
+            fprintf(f,"\n-------\n");
+        X509_print_ex_fp(f,*i,XN_FLAG_SEP_MULTILINE,0);
+    }
+}
+
+extern "C" ICredResolver* FileCredResolverFactory(const DOMElement* e)
+{
+    return new FileResolver(e);
+}
+
+extern "C" ICredResolver* KeyInfoResolverFactory(const DOMElement* e)
+{
+    return new KeyInfoResolver(e);
+}
+
index baec7da..18a8e2e 100644 (file)
@@ -12,6 +12,7 @@ libshib_la_SOURCES = \
                     AAP.cpp \
                     ClubShibPOSTProfile.cpp \
                     Constants.cpp \
+                    CredResolvers.cpp \
                     Metadata.cpp \
                     SAMLBindingFactory.cpp \
                     ShibConfig.cpp \
index f86ebee..552eaa6 100644 (file)
@@ -80,25 +80,13 @@ namespace {
 
 ShibConfig::~ShibConfig() {}
 
-extern "C" IMetadata* XMLMetadataFactory(const char* source)
-{
-    return new XMLMetadata(source);
-}
-
-extern "C" ITrust* XMLTrustFactory(const char* source)
-{
-    return new XMLTrust(source);
-}
-
-extern "C" ICredentials* XMLCredentialsFactory(const char* source)
-{
-    return new XMLCredentials(source);
-}
-
-extern "C" IAAP* XMLAAPFactory(const char* source)
-{
-    return new XMLAAP(source);
-}
+// Metadata Factories
+extern "C" IMetadata* XMLMetadataFactory(const char* source);
+extern "C" ITrust* XMLTrustFactory(const char* source);
+extern "C" ICredentials* XMLCredentialsFactory(const char* source);
+extern "C" ICredResolver* FileCredResolverFactory(const DOMElement* e);
+extern "C" ICredResolver* KeyInfoResolverFactory(const DOMElement* e);
+extern "C" IAAP* XMLAAPFactory(const char* source);
 
 extern "C" SAMLAttribute* ShibAttributeFactory(DOMElement* e)
 {
@@ -121,10 +109,16 @@ bool ShibInternalConfig::init()
     // Register extension schema.
     saml::XML::registerSchema(XML::SHIB_NS,XML::SHIB_SCHEMA_ID);
 
+    // Register metadata factories (some duplicates for backward-compatibility)
     regFactory("edu.internet2.middleware.shibboleth.metadata.XML",&XMLMetadataFactory);
+    regFactory("edu.internet2.middleware.shibboleth.metadata.provider.XML",&XMLMetadataFactory);
     regFactory("edu.internet2.middleware.shibboleth.trust.XML",&XMLTrustFactory);
-    regFactory("edu.internet2.middleware.shibboleth.creds.XML",&XMLCredentialsFactory);
+    regFactory("edu.internet2.middleware.shibboleth.trust.provider.XML",&XMLTrustFactory);
+    regFactory("edu.internet2.middleware.shibboleth.creds.provider.XML",&XMLCredentialsFactory);
+    regFactory("edu.internet2.middleware.shibboleth.creds.provider.FileCredResolver",&FileCredResolverFactory);
+    regFactory("edu.internet2.middleware.shibboleth.creds.provider.KeyInfoResolver",&KeyInfoResolverFactory);
     regFactory("edu.internet2.middleware.shibboleth.target.AAP.XML",&XMLAAPFactory);
+    regFactory("edu.internet2.middleware.shibboleth.target.AAP.provider.XML",&XMLAAPFactory);
     regFactory("edu.internet2.middleware.shibboleth.target.AttributeFactory",&ShibAttributeFactory);
 
     return true;
@@ -163,6 +157,12 @@ void ShibInternalConfig::regFactory(const char* type, CredentialsFactory* factor
     }
 }
 
+void ShibInternalConfig::regFactory(const char* type, CredResolverFactory* factory)
+{
+    if (type && factory)
+        m_credResolverFactoryMap[type]=factory;
+}
+
 void ShibInternalConfig::regFactory(const char* type, AAPFactory* factory)
 {
     if (type && factory)
@@ -182,6 +182,7 @@ void ShibInternalConfig::unregFactory(const char* type)
         m_metadataFactoryMap.erase(type);
         m_trustFactoryMap.erase(type);
         m_credFactoryMap.erase(type);
+        m_credResolverFactoryMap.erase(type);
         m_aapFactoryMap.erase(type);
     }
 }
@@ -192,13 +193,25 @@ SAMLAttributeFactory* ShibInternalConfig::getAttributeFactory(const char* type)
         m_attrFactoryMap.find((type && *type) ? type : "edu.internet2.middleware.shibboleth.target.AttributeFactory");
     if (i==m_attrFactoryMap.end())
     {
-        saml::NDC ndc("getAttributeFactory");
+        NDC ndc("getAttributeFactory");
         Category::getInstance(SHIB_LOGCAT".ShibInternalConfig").error("unknown attribute factory: %s",type);
         return NULL;
     }
     return i->second;
 }
 
+CredResolverFactory* ShibInternalConfig::getCredResolverFactory(const char* type) const
+{
+    CredResolverFactoryMap::const_iterator i=m_credResolverFactoryMap.find(type);
+    if (i==m_credResolverFactoryMap.end())
+    {
+        NDC ndc("getCredResolverFactory");
+        Category::getInstance(SHIB_LOGCAT".ShibInternalConfig").error("unknown cred resolver factory: %s",type);
+        return NULL;
+    }
+    return i->second;
+}
+
 bool ShibInternalConfig::addMetadata(const char* type, const char* source)
 {
     saml::NDC ndc("addMetadata");
index 47f4778..33817de 100644 (file)
@@ -121,22 +121,48 @@ const XMLCh XML::Literals::OriginSite[]=
 const XMLCh XML::Literals::SiteGroup[]=
 { chLatin_S, chLatin_i, chLatin_t, chLatin_e, chLatin_G, chLatin_r, chLatin_o, chLatin_u, chLatin_p, chNull };
 
+const XMLCh XML::Literals::CertificateRef[]=
+{ chLatin_C, chLatin_e, chLatin_r, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_c, chLatin_a, chLatin_t, chLatin_e,
+  chLatin_R, chLatin_e, chLatin_f, chNull };
+
+const XMLCh XML::Literals::Class[] =
+{ chLatin_C, chLatin_l, chLatin_a, chLatin_s, chLatin_s, chNull };
+
 const XMLCh XML::Literals::Credentials[] =
 { chLatin_C, chLatin_r, chLatin_e, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_a, chLatin_l, chLatin_s, chNull };
 
+const XMLCh XML::Literals::CustomCredResolver[]=
+{ chLatin_C, chLatin_u, chLatin_s, chLatin_t, chLatin_o, chLatin_m, chLatin_C, chLatin_r, chLatin_e, chLatin_d,
+  chLatin_R, chLatin_e, chLatin_s, chLatin_o, chLatin_l, chLatin_v, chLatin_e, chLatin_r, chNull };
+
 const XMLCh XML::Literals::Exponent[] =
 { chLatin_E, chLatin_x, chLatin_p, chLatin_o, chLatin_n, chLatin_e, chLatin_n, chLatin_t, chNull };
 
+const XMLCh XML::Literals::FileCredResolver[]=
+{ chLatin_F, chLatin_i, chLatin_l, chLatin_e, chLatin_C, chLatin_r, chLatin_e, chLatin_d,
+  chLatin_R, chLatin_e, chLatin_s, chLatin_o, chLatin_l, chLatin_v, chLatin_e, chLatin_r, chNull };
+
+const XMLCh XML::Literals::Id[] = { chLatin_I, chLatin_d, chNull };
+
 const XMLCh XML::Literals::KeyAuthority[] =
 { chLatin_K, chLatin_e, chLatin_y,
   chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_o, chLatin_r, chLatin_i, chLatin_t, chLatin_y, chNull };
 
+const XMLCh XML::Literals::KeyRef[] =
+{ chLatin_K, chLatin_e, chLatin_y, chLatin_R, chLatin_e, chLatin_f, chNull };
+
 const XMLCh XML::Literals::KeyUse[] =
 { chLatin_K, chLatin_e, chLatin_y, chLatin_U, chLatin_s, chLatin_e, chNull };
 
 const XMLCh XML::Literals::Modulus[] =
 { chLatin_M, chLatin_o, chLatin_d, chLatin_u, chLatin_l, chLatin_u, chLatin_s, chNull };
 
+const XMLCh XML::Literals::Password[] =
+{ chLatin_P, chLatin_a, chLatin_s, chLatin_s, chLatin_w, chLatin_o, chLatin_r, chLatin_d, chNull };
+
+const XMLCh XML::Literals::Path[] =
+{ chLatin_P, chLatin_a, chLatin_t, chLatin_h, chNull };
+
 const XMLCh XML::Literals::RelyingParty[] =
 { chLatin_R, chLatin_e, chLatin_l, chLatin_y, chLatin_i, chLatin_n, chLatin_g,
   chLatin_P, chLatin_a, chLatin_r, chLatin_t, chLatin_y, chNull };
index 11166de..7679c0b 100644 (file)
@@ -47,7 +47,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* XMLTrust.h - a trust implementation that uses an XML file
+/* XMLCredentials.cpp - a credentials implementation that uses an XML file
 
    Scott Cantor
    9/27/02
@@ -70,110 +70,72 @@ using namespace saml;
 using namespace log4cpp;
 using namespace std;
 
-class shibboleth::XMLCredentialsImpl
-{
-public:
-    XMLCredentialsImpl(const char* pathname);
-    ~XMLCredentialsImpl();
+namespace shibboleth {
     
-    struct KeyUse
+    class XMLCredentialsImpl
     {
-        KeyUse() {}
-        ~KeyUse();
+    public:
+        XMLCredentialsImpl(const char* pathname);
+        ~XMLCredentialsImpl();
+        
+        typedef map<string,ICredResolver*> resolvermap_t;
+        resolvermap_t m_resolverMap;
 
-        bool attach(SSL_CTX* ctx);
+        struct KeyUse
+        {
+            KeyUse(resolvermap_t& resolverMap, const XMLCh* keyref, const XMLCh* certref=NULL);
+            
+            ICredResolver* m_key;
+            ICredResolver* m_cert;
+            vector<pair<const XMLCh*,bool> > m_relying;
+        };
         
-        enum format_t { X509DATA, DER, PEM };
+        vector<KeyUse*> m_keyuses;
+        typedef multimap<pair<const XMLCh*,bool>,KeyUse*> BindingMap;
+        BindingMap m_bindings;
         
-        format_t m_certtype, m_keytype;
-        vector<X509*> m_certs;
-        string m_certfile, m_keyfile;
-        vector<pair<const XMLCh*,bool> > m_relying;
+        DOMDocument* m_doc;
     };
-    
-    vector<KeyUse*> m_keyuses;
-    typedef multimap<pair<const XMLCh*,bool>,KeyUse*> BindingMap;
-    BindingMap m_bindings;
-    
-    DOMDocument* m_doc;
-};
 
-XMLCredentialsImpl::KeyUse::~KeyUse()
+    class XMLCredentials : public ICredentials
+    {
+    public:
+        XMLCredentials(const char* pathname);
+        ~XMLCredentials() { delete m_lock; delete m_impl; }
+        bool attach(const XMLCh* subject, const ISite* relyingParty, SSL_CTX* ctx) const;
+
+    private:
+        void lock();
+        void unlock() { m_lock->unlock(); }
+        std::string m_source;
+        time_t m_filestamp;
+        RWLock* m_lock;
+        XMLCredentialsImpl* m_impl;
+    };
+
+}
+
+extern "C" ICredentials* XMLCredentialsFactory(const char* source)
 {
-    for (vector<X509*>::iterator i=m_certs.begin(); i!=m_certs.end(); i++)
-        X509_free(*i);
+    return new XMLCredentials(source);
 }
 
-bool XMLCredentialsImpl::KeyUse::attach(SSL_CTX* ctx)
+XMLCredentialsImpl::KeyUse::KeyUse(resolvermap_t& resolverMap, const XMLCh* keyref, const XMLCh* certref) : m_key(NULL), m_cert(NULL)
 {
-    switch (m_certtype)
-    {
-        case PEM:
-            if (SSL_CTX_use_certificate_chain_file(ctx, m_certfile.c_str()) != 1)
-            {
-                log_openssl();
-                throw TrustException("XMLCredentials::KeyUse::attach() unable to set PEM certificate chain");
-            }
-            break;
-            
-        case DER:
-            if (SSL_CTX_use_certificate_file(ctx, m_certfile.c_str(), SSL_FILETYPE_ASN1) != 1)
-            {
-                log_openssl();
-                throw TrustException("XMLCredentials::KeyUse::attach() unable to set DER certificate");
-            }
-            break;
-            
-        case X509DATA:
-            for (vector<X509*>::reverse_iterator i=m_certs.rbegin(); i!=m_certs.rend(); i++)
-            {
-                if (i==m_certs.rbegin())
-                {
-                    if (SSL_CTX_use_certificate(ctx, *i) != 1)
-                    {
-                        log_openssl();
-                        throw TrustException("XMLCredentials::KeyUse::attach() unable to set certificate from X509Data");
-                    }
-                }
-                else
-                {
-                    // When we add extra certs, they don't get ref counted, so we need to duplicate them.
-                    X509* dup = X509_dup(*i);
-                    if (SSL_CTX_add_extra_chain_cert(ctx, dup) != 0)
-                    {
-                        X509_free(dup);
-                        log_openssl();
-                        throw TrustException("XMLCredentials::KeyUse::attach() unable to add CA certificate from X509Data");
-                    }
-                }
-            }
-    }
+    auto_ptr<char> temp(XMLString::transcode(keyref));
+    resolvermap_t::iterator i=resolverMap.find(temp.get());
+    if (i==resolverMap.end())
+        throw MetadataException(string("XMLCredentialsImpl::KeyUse::KeyUse() unable to find valid key reference (") + temp.get() + ")");
+    m_key=i->second;
     
-    switch (m_keytype)
+    if (certref && *certref)
     {
-        case PEM:
-            if (SSL_CTX_use_PrivateKey_file(ctx, m_keyfile.c_str(), SSL_FILETYPE_PEM) != 1)
-            {
-                log_openssl();
-                throw TrustException("XMLCredentials::KeyUse::attach() unable to set PEM private key");
-            }
-            break;
-            
-        case DER:
-            if (SSL_CTX_use_PrivateKey_file(ctx, m_keyfile.c_str(), SSL_FILETYPE_ASN1) != 1)
-            {
-                log_openssl();
-                throw TrustException("XMLCredentials::KeyUse::attach() unable to set PEM private key");
-            }
+        auto_ptr<char> temp2(XMLString::transcode(certref));
+        i=resolverMap.find(temp2.get());
+        if (i==resolverMap.end())
+            throw MetadataException(string("XMLCredentialsImpl::KeyUse::KeyUse() unable to find valid certificate reference (") + temp2.get() + ")");
+        m_cert=i->second;
     }
-    
-    if (!SSL_CTX_check_private_key(ctx))
-    {
-        log_openssl();
-        throw TrustException("XMLCredentials::KeyUse::attach found mismatch between the private key and certificate");
-    }
-    
-    return true;
 }
 
 XMLCredentialsImpl::XMLCredentialsImpl(const char* pathname) : m_doc(NULL)
@@ -199,120 +161,51 @@ XMLCredentialsImpl::XMLCredentialsImpl(const char* pathname) : m_doc(NULL)
             throw MetadataException("Construction requires a valid creds file: (shib:Credentials as root element)");
         }
 
-        // Loop over the KeyUse elements.
-        DOMNodeList* nlist=e->getElementsByTagNameNS(XML::SHIB_NS,SHIB_L(KeyUse));
-        for (int i=0; nlist && i<nlist->getLength(); i++)
+        // Process everything up to the first shib:KeyUse as a resolver.
+        DOMElement* child=saml::XML::getFirstChildElement(e);
+        while (!saml::XML::isElementNamed(child,XML::SHIB_NS,SHIB_L(KeyUse)))
         {
-            auto_ptr<KeyUse> ku(new KeyUse());
-
-            bool key=false,cert=false;
+            CredResolverFactory* factory=NULL;
+            auto_ptr<char> id(XMLString::transcode(child->getAttributeNS(NULL,SHIB_L(Id))));
             
-            // Grab all the RetrievalMethods for external material.
-            DOMNodeList* extlist=static_cast<DOMElement*>(nlist->item(i))->getElementsByTagNameNS(
-                saml::XML::XMLSIG_NS,SHIB_L(RetrievalMethod)
-                );
-            for (int j=0; (!key || !cert) && extlist && j<extlist->getLength(); j++)
+            if (saml::XML::isElementNamed(child,XML::SHIB_NS,SHIB_L(FileCredResolver)))
+                factory=ShibConfig::getConfig().getCredResolverFactory("edu.internet2.middleware.shibboleth.creds.provider.FileCredResolver");
+            else if (saml::XML::isElementNamed(child,saml::XML::XMLSIG_NS,L(KeyInfo)))
+                factory=ShibConfig::getConfig().getCredResolverFactory("edu.internet2.middleware.shibboleth.creds.provider.KeyInfoResolver");
+            else if (saml::XML::isElementNamed(child,XML::SHIB_NS,SHIB_L(CustomCredResolver)))
             {
-                DOMElement* method=static_cast<DOMElement*>(extlist->item(j));
-                const XMLCh* rmtype=method->getAttributeNS(NULL,SHIB_L(Type));
-                auto_ptr<char> uri(XMLString::transcode(method->getAttributeNS(NULL,SHIB_L(URI))));
-                
-                // Is the URI locally accessible as a relative URL?
-#ifdef WIN32
-                struct _stat stat_buf;
-                if (_stat(uri.get(), &stat_buf) != 0)
-#else
-                struct stat stat_buf;
-                if (stat(uri.get(), &stat_buf) != 0)
-#endif
-                {
-                    log.warn("Credential referenced by ds:RetrievalMethod can't be opened");
-                    continue;
-                }
-                
-                if (!XMLString::compareString(rmtype,shibboleth::Constants::XMLSIG_RETMETHOD_RAWX509))
-                {
-                    if (cert)
-                        log.warn("Found another certificate credential (DER), replacing the original with it");
-                    ku->m_certfile=uri.get();
-                    ku->m_certtype=KeyUse::DER;
-                    cert=true;
-                }
-                else if (!XMLString::compareString(rmtype,shibboleth::Constants::SHIB_RETMETHOD_PEMX509))
-                {
-                    if (cert)
-                        log.warn("Found another certificate credential (PEM), replacing the original with it");
-                    ku->m_certfile=uri.get();
-                    ku->m_certtype=KeyUse::PEM;
-                    cert=true;
-                }
-                else if (!XMLString::compareString(rmtype,shibboleth::Constants::SHIB_RETMETHOD_PEMRSA))
-                {
-                    if (key)
-                        log.warn("Found another private key credential (PEM/RSA), replacing the original with it");
-                    ku->m_keyfile=uri.get();
-                    ku->m_keytype=KeyUse::PEM;
-                    key=true;
-                }
-                else if (!XMLString::compareString(rmtype,shibboleth::Constants::SHIB_RETMETHOD_DERRSA))
-                {
-                    if (key)
-                        log.warn("Found another private key credential (DER/RSA), replacing the original with it");
-                    ku->m_keyfile=uri.get();
-                    ku->m_keytype=KeyUse::DER;
-                    key=true;
-                }
+                auto_ptr<char> c(XMLString::transcode(child->getAttributeNS(NULL,SHIB_L(Class))));
+                factory=ShibConfig::getConfig().getCredResolverFactory(c.get());
             }
             
-            if (!cert)
+            if (factory)
             {
-                // Is there an X509Data?
-                DOMNodeList* x509data=static_cast<DOMElement*>(nlist->item(i))->getElementsByTagNameNS(
-                    saml::XML::XMLSIG_NS,L(X509Data)
-                    );
-                if (x509data && x509data->getLength())
+                try
                 {
-                    if (x509data->getLength()>1)
-                        log.warn("Found multiple certificate chains, using the first");
-            
-                    // Grab up any X509Certificate elements, and flatten into one list.
-                    DOMNodeList* certlist=static_cast<DOMElement*>(x509data->item(0))->getElementsByTagNameNS(
-                        saml::XML::XMLSIG_NS,L(X509Certificate)
-                        );
-                    for (int k=0; certlist && k<certlist->getLength(); k++)
-                    {
-                        auto_ptr<char> blob(XMLString::transcode(certlist->item(k)->getFirstChild()->getNodeValue()));
-                        X509* x=B64_to_X509(blob.get());
-                        if (x)
-                            ku->m_certs.push_back(x);
-                        else
-                            log.warn("Unable to parse ds:X509Certificate element, can't include in chain");
-                    }
-                    
-                    if (ku->m_certs.size()>0)
-                    {
-                        ku->m_certtype=KeyUse::X509DATA;
-                        cert=true;
-                    }
-                    else
-                        log.warn("Found no inline certificates in the ds:X509Data element, ignoring it");
+                    ICredResolver* cr=(*factory)(child);
+                    m_resolverMap[id.get()]=cr;
+                }
+                catch (SAMLException& e)
+                {
+                    log.error("failed to instantiate credential resolver (%s): %s", id.get(), e.what());
                 }
             }
             
-            if (!cert)
-            {
-                log.error("Found no acceptable certificate in shib:KeyUse element, ignoring it");
-                continue;
-            }
-            
-            if (!key)
-            {
-                log.error("Found no acceptable private/secret key in shib:KeyUse element, ignoring it");
-                continue;
-            }
-            
+            child=saml::XML::getNextSiblingElement(child);
+        }
+
+        // Now loop over the KeyUse elements.
+        while (child && saml::XML::isElementNamed(child,XML::SHIB_NS,SHIB_L(KeyUse)))
+        {
+            KeyUse* ku = new KeyUse(
+                m_resolverMap,
+                child->getAttributeNS(NULL,SHIB_L(KeyRef)),
+                child->getAttributeNS(NULL,SHIB_L(CertificateRef))
+                );
+            m_keyuses.push_back(ku);
+
             // Pull in the relying parties.
-            DOMNodeList* parties=static_cast<DOMElement*>(nlist->item(i))->getElementsByTagNameNS(XML::SHIB_NS,SHIB_L(RelyingParty));
+            DOMNodeList* parties=child->getElementsByTagNameNS(XML::SHIB_NS,SHIB_L(RelyingParty));
             int m=0;
             while (parties && m<parties->getLength())
             {
@@ -333,7 +226,7 @@ XMLCredentialsImpl::XMLCredentialsImpl(const char* pathname) : m_doc(NULL)
                 ku->m_relying.push_back(pair<const XMLCh*,bool>(NULL,false));
             
             // Now map the subjects to the credentials.
-            DOMNodeList* subs=static_cast<DOMElement*>(nlist->item(i))->getElementsByTagNameNS(XML::SHIB_NS,L(Subject));
+            DOMNodeList* subs=child->getElementsByTagNameNS(XML::SHIB_NS,L(Subject));
             int l=0;
             while (subs && l<subs->getLength())
             {
@@ -345,15 +238,15 @@ XMLCredentialsImpl::XMLCredentialsImpl(const char* pathname) : m_doc(NULL)
                     const XMLCh* regexp=
                         static_cast<DOMElement*>(subs->item(l))->getAttributeNS(NULL,SHIB_L(regexp));
                     bool flag=(!XMLString::compareString(regexp,one) || !XMLString::compareString(regexp,tru));
-                    m_bindings.insert(BindingMap::value_type(pair<const XMLCh*,bool>(name,flag),ku.get()));
+                    m_bindings.insert(BindingMap::value_type(pair<const XMLCh*,bool>(name,flag),ku));
                 }
                 l++;
             }
             // If no Subjects, this is a catch-all binding.
             if (l==0)
-                m_bindings.insert(BindingMap::value_type(pair<const XMLCh*,bool>(NULL,false),ku.get()));
+                m_bindings.insert(BindingMap::value_type(pair<const XMLCh*,bool>(NULL,false),ku));
 
-            m_keyuses.push_back(ku.release());
+            child=saml::XML::getNextSiblingElement(child);
         }
     }
     catch (SAMLException& e)
@@ -361,6 +254,8 @@ XMLCredentialsImpl::XMLCredentialsImpl(const char* pathname) : m_doc(NULL)
         log.errorStream() << "XML error while parsing creds configuration: " << e.what() << CategoryStream::ENDLINE;
         for (vector<KeyUse*>::iterator i=m_keyuses.begin(); i!=m_keyuses.end(); i++)
             delete (*i);
+        for (resolvermap_t::iterator j=m_resolverMap.begin(); j!=m_resolverMap.end(); j++)
+            delete j->second;
         if (m_doc)
             m_doc->release();
         throw;
@@ -370,6 +265,8 @@ XMLCredentialsImpl::XMLCredentialsImpl(const char* pathname) : m_doc(NULL)
         log.error("Unexpected error while parsing creds configuration");
         for (vector<KeyUse*>::iterator i=m_keyuses.begin(); i!=m_keyuses.end(); i++)
             delete (*i);
+        for (resolvermap_t::iterator j=m_resolverMap.begin(); j!=m_resolverMap.end(); j++)
+            delete j->second;
         if (m_doc)
             m_doc->release();
         throw;
@@ -380,6 +277,8 @@ XMLCredentialsImpl::~XMLCredentialsImpl()
 {
     for (vector<KeyUse*>::iterator i=m_keyuses.begin(); i!=m_keyuses.end(); i++)
         delete (*i);
+    for (resolvermap_t::iterator j=m_resolverMap.begin(); j!=m_resolverMap.end(); j++)
+        delete j->second;
     if (m_doc)
         m_doc->release();
 }
@@ -398,12 +297,6 @@ XMLCredentials::XMLCredentials(const char* pathname) : m_filestamp(0), m_source(
     m_lock=RWLock::create();
 }
 
-XMLCredentials::~XMLCredentials()
-{
-    delete m_lock;
-    delete m_impl;
-}
-
 void XMLCredentials::lock()
 {
     m_lock->rdlock();
@@ -454,11 +347,6 @@ void XMLCredentials::lock()
     }
 }
 
-void XMLCredentials::unlock()
-{
-    m_lock->unlock();
-}
-
 
 bool XMLCredentials::attach(const XMLCh* subject, const ISite* relyingParty, SSL_CTX* ctx) const
 {
@@ -543,8 +431,28 @@ bool XMLCredentials::attach(const XMLCh* subject, const ISite* relyingParty, SSL
         
         if (match)
         {
-            // We have the credentials to use...
-            return i->second->attach(ctx);
+            try
+            {
+                i->second->m_key->resolveKey(ctx);
+                if (i->second->m_cert)
+                    i->second->m_cert->resolveCert(ctx);
+
+                if (!SSL_CTX_check_private_key(ctx))
+                {
+                    log_openssl();
+                    throw MetadataException("XMLCredentials::attach() found mismatch between the private key and certificate used");
+                }
+            }
+            catch (SAMLException& e)
+            {
+                Category& log=Category::getInstance(SHIB_LOGCAT".XMLCredentials");
+                log.error("caught a SAML exception while attaching credentials: %s", e.what());
+            }
+            catch (...)
+            {
+                Category& log=Category::getInstance(SHIB_LOGCAT".XMLCredentials");
+                log.error("caught an unknown exception while attaching credentials");
+            }
         }
     }
 
index bf44b39..af1cc41 100644 (file)
@@ -47,7 +47,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* XMLMetadata.h - a metadata implementation that uses an XML-based registry
+/* XMLMetadata.cpp - a metadata implementation that uses an XML-based registry
 
    Scott Cantor
    9/27/02
@@ -69,76 +69,101 @@ using namespace saml;
 using namespace log4cpp;
 using namespace std;
 
-class shibboleth::XMLMetadataImpl
-{
-public:
-    XMLMetadataImpl(const char* pathname);
-    ~XMLMetadataImpl();
-    
-    class ContactInfo : public IContactInfo
+namespace shibboleth {
+
+    class XMLMetadataImpl
     {
     public:
-        ContactInfo(ContactType type, const XMLCh* name, const XMLCh* email)
-            : m_type(type), m_name(XMLString::transcode(name)), m_email(XMLString::transcode(email)) {}
+        XMLMetadataImpl(const char* pathname);
+        ~XMLMetadataImpl();
+    
+        class ContactInfo : public IContactInfo
+        {
+        public:
+            ContactInfo(ContactType type, const XMLCh* name, const XMLCh* email)
+                : m_type(type), m_name(XMLString::transcode(name)), m_email(XMLString::transcode(email)) {}
         
-        ContactType getType() const { return m_type; }
-        const char* getName() const { return m_name.get(); }            
-        const char* getEmail() const { return m_email.get(); }
+            ContactType getType() const { return m_type; }
+            const char* getName() const { return m_name.get(); }            
+            const char* getEmail() const { return m_email.get(); }
         
-    private:
-        ContactType m_type;
-        std::auto_ptr<char> m_name, m_email;
-    };
+        private:
+            ContactType m_type;
+            std::auto_ptr<char> m_name, m_email;
+        };
         
-    class Authority : public IAuthority
-    {
-    public:
-        Authority(const XMLCh* name, const XMLCh* url) : m_name(name), m_url(XMLString::transcode(url)) {}
+        class Authority : public IAuthority
+        {
+        public:
+            Authority(const XMLCh* name, const XMLCh* url) : m_name(name), m_url(XMLString::transcode(url)) {}
         
-        const XMLCh* getName() const { return m_name; }
-        const char* getURL() const { return m_url.get(); }
+            const XMLCh* getName() const { return m_name; }
+            const char* getURL() const { return m_url.get(); }
         
-    private:
-        const XMLCh* m_name;
-        auto_ptr<char> m_url;
-    };
+        private:
+            const XMLCh* m_name;
+            auto_ptr<char> m_url;
+        };
     
-    class OriginSite : public IOriginSite
+        class OriginSite : public IOriginSite
+        {
+        public:
+            OriginSite(const XMLCh* name, const XMLCh* errorURL)
+                : m_name(name), m_errorURL(XMLString::transcode(errorURL)) {}
+            ~OriginSite();
+        
+            const XMLCh* getName() const {return m_name;}
+            Iterator<const XMLCh*> getGroups() const {return m_groups;}
+            Iterator<const IContactInfo*> getContacts() const {return m_contacts;}
+            const char* getErrorURL() const {return m_errorURL.get();}
+            bool validate(Iterator<XSECCryptoX509*> certs) const {Trust t; return t.validate(this,certs);}
+            bool validate(Iterator<const XMLCh*> certs) const {Trust t; return t.validate(this,certs);}
+            Iterator<const IAuthority*> getHandleServices() const {return m_handleServices;}
+            Iterator<const IAuthority*> getAttributeAuthorities() const {return m_attributes;}
+            Iterator<std::pair<const XMLCh*,bool> > getSecurityDomains() const {return m_domains;}
+
+        private:
+            friend class XMLMetadataImpl;
+            const XMLCh* m_name;
+            auto_ptr<char> m_errorURL;
+            vector<const IContactInfo*> m_contacts;
+            vector<const IAuthority*> m_handleServices;
+            vector<const IAuthority*> m_attributes;
+            vector<pair<const XMLCh*,bool> > m_domains;
+            vector<const XMLCh*> m_groups;
+        };
+
+    #ifdef HAVE_GOOD_STL
+        typedef map<xstring,OriginSite*> sitemap_t;
+    #else
+        typedef map<string,OriginSite*> sitemap_t;
+    #endif
+        sitemap_t m_sites;
+        DOMDocument* m_doc;
+    };
+
+    class XMLMetadata : public IMetadata
     {
     public:
-        OriginSite(const XMLCh* name, const XMLCh* errorURL)
-            : m_name(name), m_errorURL(XMLString::transcode(errorURL)) {}
-        ~OriginSite();
-        
-        const XMLCh* getName() const {return m_name;}
-        Iterator<const XMLCh*> getGroups() const {return m_groups;}
-        Iterator<const IContactInfo*> getContacts() const {return m_contacts;}
-        const char* getErrorURL() const {return m_errorURL.get();}
-        bool validate(Iterator<XSECCryptoX509*> certs) const {Trust t; return t.validate(this,certs);}
-        bool validate(Iterator<const XMLCh*> certs) const {Trust t; return t.validate(this,certs);}
-        Iterator<const IAuthority*> getHandleServices() const {return m_handleServices;}
-        Iterator<const IAuthority*> getAttributeAuthorities() const {return m_attributes;}
-        Iterator<std::pair<const XMLCh*,bool> > getSecurityDomains() const {return m_domains;}
+        XMLMetadata(const char* pathname);
+        ~XMLMetadata() { delete m_lock; delete m_impl; }
+
+        void lock();
+        void unlock() { m_lock->unlock(); }
+        const ISite* lookup(const XMLCh* site) const;
 
     private:
-        friend class XMLMetadataImpl;
-        const XMLCh* m_name;
-        auto_ptr<char> m_errorURL;
-        vector<const IContactInfo*> m_contacts;
-        vector<const IAuthority*> m_handleServices;
-        vector<const IAuthority*> m_attributes;
-        vector<pair<const XMLCh*,bool> > m_domains;
-        vector<const XMLCh*> m_groups;
+        std::string m_source;
+        time_t m_filestamp;
+        RWLock* m_lock;
+        XMLMetadataImpl* m_impl;
     };
+}
 
-#ifdef HAVE_GOOD_STL
-    typedef map<xstring,OriginSite*> sitemap_t;
-#else
-    typedef map<string,OriginSite*> sitemap_t;
-#endif
-    sitemap_t m_sites;
-    DOMDocument* m_doc;
-};
+extern "C" IMetadata* XMLMetadataFactory(const char* source)
+{
+    return new XMLMetadata(source);
+}
 
 XMLMetadataImpl::OriginSite::~OriginSite()
 {
@@ -303,12 +328,6 @@ XMLMetadata::XMLMetadata(const char* pathname) : m_filestamp(0), m_source(pathna
     m_lock=RWLock::create();
 }
 
-XMLMetadata::~XMLMetadata()
-{
-    delete m_lock;
-    delete m_impl;
-}
-
 void XMLMetadata::lock()
 {
     m_lock->rdlock();
@@ -359,11 +378,6 @@ void XMLMetadata::lock()
     }
 }
 
-void XMLMetadata::unlock()
-{
-    m_lock->unlock();
-}
-
 const ISite* XMLMetadata::lookup(const XMLCh* site) const
 {
 #ifdef HAVE_GOOD_STL
index 711af5f..c0a6b1b 100644 (file)
@@ -47,7 +47,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* XMLTrust.h - a trust implementation that uses an XML file
+/* XMLTrust.cpp - a trust implementation that uses an XML file
 
    Scott Cantor
    9/27/02
@@ -80,31 +80,60 @@ int verify_callback(int ok, X509_STORE_CTX* store)
     return ok;
 }
 
-class shibboleth::XMLTrustImpl
-{
-public:
-    XMLTrustImpl(const char* pathname);
-    ~XMLTrustImpl();
+namespace shibboleth {
+
+    class XMLTrustImpl
+    {
+    public:
+        XMLTrustImpl(const char* pathname);
+        ~XMLTrustImpl();
+        
+        struct KeyAuthority
+        {
+            KeyAuthority() : m_store(NULL), m_depth(0), m_type(authority) {}
+            ~KeyAuthority();
+            X509_STORE* getX509Store(bool cached=true);
     
-    struct KeyAuthority
+            vector<XSECCryptoX509*> m_certs;
+            vector<X509*> m_nativecerts;
+            X509_STORE* m_store;
+            unsigned short m_depth;
+            enum {authority, entity} m_type;
+        };
+        
+        vector<KeyAuthority*> m_keyauths;
+        typedef map<pair<const XMLCh*,bool>,KeyAuthority*> BindingMap;
+        BindingMap m_bindings;
+        
+        DOMDocument* m_doc;
+    };
+
+    class XMLTrust : public ITrust
     {
-        KeyAuthority() : m_store(NULL), m_depth(0), m_type(authority) {}
-        ~KeyAuthority();
-        X509_STORE* getX509Store(bool cached=true);
-
-        vector<XSECCryptoX509*> m_certs;
-        vector<X509*> m_nativecerts;
-        X509_STORE* m_store;
-        unsigned short m_depth;
-        enum {authority, entity} m_type;
+    public:
+        XMLTrust(const char* pathname);
+        ~XMLTrust() { delete m_lock; delete m_impl; }
+
+        void lock();
+        void unlock() { m_lock->unlock(); }
+        saml::Iterator<XSECCryptoX509*> getCertificates(const XMLCh* subject) const;
+        bool validate(const ISite* site, saml::Iterator<XSECCryptoX509*> certs) const;
+        bool validate(const ISite* site, saml::Iterator<const XMLCh*> certs) const;
+        bool attach(const ISite* site, SSL_CTX* ctx) const;
+
+    private:
+        std::string m_source;
+        time_t m_filestamp;
+        RWLock* m_lock;
+        XMLTrustImpl* m_impl;
     };
-    
-    vector<KeyAuthority*> m_keyauths;
-    typedef map<pair<const XMLCh*,bool>,KeyAuthority*> BindingMap;
-    BindingMap m_bindings;
-    
-    DOMDocument* m_doc;
-};
+
+}
+
+extern "C" ITrust* XMLTrustFactory(const char* source)
+{
+    return new XMLTrust(source);
+}
 
 X509_STORE* XMLTrustImpl::KeyAuthority::getX509Store(bool cached)
 {
@@ -279,12 +308,6 @@ XMLTrust::XMLTrust(const char* pathname) : m_filestamp(0), m_source(pathname), m
     m_lock=RWLock::create();
 }
 
-XMLTrust::~XMLTrust()
-{
-    delete m_lock;
-    delete m_impl;
-}
-
 void XMLTrust::lock()
 {
     m_lock->rdlock();
@@ -319,12 +342,12 @@ void XMLTrust::lock()
                     saml::NDC ndc("lock");
                     Category::getInstance(SHIB_LOGCAT".XMLTrust").error("failed to reload trust metadata, sticking with what we have: %s", e.what());
                 }
-/*                catch(...)
+                catch(...)
                 {
                     m_lock->unlock();
                     saml::NDC ndc("lock");
                     Category::getInstance(SHIB_LOGCAT".XMLTrust").error("caught an unknown exception, sticking with what we have");
-                } */
+                }
             }
             else
             {
@@ -335,11 +358,6 @@ void XMLTrust::lock()
     }
 }
 
-void XMLTrust::unlock()
-{
-    m_lock->unlock();
-}
-
 Iterator<XSECCryptoX509*> XMLTrust::getCertificates(const XMLCh* subject) const
 {
     // Find the first matching entity binding.
index b84850a..32b1b59 100644 (file)
 
 namespace shibboleth
 {
-    class XMLMetadataImpl;
-    class XMLMetadata : public IMetadata
-    {
-    public:
-        XMLMetadata(const char* pathname);
-        ~XMLMetadata();
-
-        void lock();
-        void unlock();
-        const ISite* lookup(const XMLCh* site) const;
-
-    private:
-        std::string m_source;
-        time_t m_filestamp;
-        RWLock* m_lock;
-        XMLMetadataImpl* m_impl;
-    };
-
-    class XMLTrustImpl;
-    class XMLTrust : public ITrust
-    {
-    public:
-        XMLTrust(const char* pathname);
-        ~XMLTrust();
-
-        void lock();
-        void unlock();
-        saml::Iterator<XSECCryptoX509*> getCertificates(const XMLCh* subject) const;
-        bool validate(const ISite* site, saml::Iterator<XSECCryptoX509*> certs) const;
-        bool validate(const ISite* site, saml::Iterator<const XMLCh*> certs) const;
-        bool attach(const ISite* site, SSL_CTX* ctx) const;
-
-    private:
-        std::string m_source;
-        time_t m_filestamp;
-        RWLock* m_lock;
-        XMLTrustImpl* m_impl;
-    };
-
-    class XMLCredentialsImpl;
-    class XMLCredentials : public ICredentials
-    {
-    public:
-        XMLCredentials(const char* pathname);
-        ~XMLCredentials();
-        bool attach(const XMLCh* subject, const ISite* relyingParty, SSL_CTX* ctx) const;
-
-    private:
-        void lock();
-        void unlock();
-        std::string m_source;
-        time_t m_filestamp;
-        RWLock* m_lock;
-        XMLCredentialsImpl* m_impl;
-    };
-
-    class XMLAAPImpl;
-    class XMLAAP : public IAAP
-    {
-    public:
-        XMLAAP(const char* pathname);
-        ~XMLAAP();
-        
-        void lock();
-        void unlock();
-        const IAttributeRule* lookup(const XMLCh* attrName, const XMLCh* attrNamespace=NULL) const;
-        const IAttributeRule* lookup(const char* alias) const;
-        saml::Iterator<const IAttributeRule*> getAttributeRules() const;
-
-    private:
-        std::string m_source;
-        time_t m_filestamp;
-        RWLock* m_lock;
-        XMLAAPImpl* m_impl;
-    };
-    
     class ClubShibPOSTProfile : public ShibPOSTProfile
     {
     public:
@@ -213,6 +137,7 @@ namespace shibboleth
         void regFactory(const char* type, MetadataFactory* factory);
         void regFactory(const char* type, TrustFactory* factory);
         void regFactory(const char* type, CredentialsFactory* factory);
+        void regFactory(const char* type, CredResolverFactory* factory);
         void regFactory(const char* type, AAPFactory* factory);
         void regFactory(const char* type, saml::SAMLAttributeFactory* factory);
         void unregFactory(const char* type);
@@ -222,6 +147,7 @@ namespace shibboleth
         saml::Iterator<IMetadata*> getMetadataProviders() const {return m_providers;}
         saml::Iterator<ITrust*> getTrustProviders() const {return m_trust_providers;}
         saml::Iterator<ICredentials*> getCredentialProviders() const {return m_cred_providers;}
+        CredResolverFactory* getCredResolverFactory(const char* type) const;
         saml::Iterator<IAAP*> getAAPProviders() const {return m_aap_providers;}
         saml::SAMLAttributeFactory* getAttributeFactory(const char* type) const;
 
@@ -234,11 +160,13 @@ namespace shibboleth
         typedef std::map<std::string, MetadataFactory*> MetadataFactoryMap;
         typedef std::map<std::string, TrustFactory*> TrustFactoryMap;
         typedef std::map<std::string, CredentialsFactory*> CredentialsFactoryMap;
+        typedef std::map<std::string, CredResolverFactory*> CredResolverFactoryMap;
         typedef std::map<std::string, AAPFactory*> AAPFactoryMap;
         typedef std::map<std::string, saml::SAMLAttributeFactory*> AttributeFactoryMap;
         MetadataFactoryMap m_metadataFactoryMap;
         TrustFactoryMap m_trustFactoryMap;
         CredentialsFactoryMap m_credFactoryMap;
+        CredResolverFactoryMap m_credResolverFactoryMap;
         AAPFactoryMap m_aapFactoryMap;
         AttributeFactoryMap m_attrFactoryMap;
         std::vector<IMetadata*> m_providers;
index acb07b4..08242d1 100644 (file)
@@ -53,7 +53,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 log4cpp.lib xerces-c_2.lib xsec_lib_02.lib saml_4.lib libeay32.lib ssleay32.lib /nologo /dll /machine:I386 /out:"Release/shib_5.dll" /libpath:"..\..\..\opensaml\c\saml\Release" /libpath:"\openssl-0.9.7b\out32dll"
+# ADD LINK32 log4cpp.lib xerces-c_2.lib saml_4.lib libeay32.lib ssleay32.lib xsec_1.lib /nologo /dll /machine:I386 /out:"Release/shib_5.dll" /libpath:"..\..\..\opensaml\c\saml\Release" /libpath:"\openssl-0.9.7c\out32dll"
 
 !ELSEIF  "$(CFG)" == "shib - Win32 Debug"
 
@@ -79,7 +79,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 log4cppD.lib xerces-c_2D.lib xsec_lib_02D.lib saml_4D.lib libeay32.lib ssleay32.lib /nologo /dll /debug /machine:I386 /out:"Debug/shib_5D.dll" /pdbtype:sept /libpath:"..\..\..\opensaml\c\saml\Debug" /libpath:"\openssl-0.9.7b\out32dll.dbg"
+# ADD LINK32 log4cppD.lib xerces-c_2D.lib saml_4D.lib libeay32.lib ssleay32.lib xsec_1D.lib /nologo /dll /debug /machine:I386 /out:"Debug/shib_5D.dll" /pdbtype:sept /libpath:"..\..\..\opensaml\c\saml\Debug" /libpath:"\openssl-0.9.7c\out32dll.dbg"
 
 !ENDIF 
 
@@ -105,6 +105,10 @@ SOURCE=.\Constants.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\CredResolvers.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\internal.h
 # End Source File
 # Begin Source File
index a71791b..0083591 100644 (file)
@@ -157,6 +157,15 @@ namespace shibboleth
         virtual ~ICredentials() {}
     };
     
+    struct SHIB_EXPORTS ICredResolver
+    {
+        virtual void resolveKey(SSL_CTX* ctx) const=0;
+        virtual void resolveCert(SSL_CTX* ctx) const=0;
+        virtual void dump(FILE* f) const=0;
+        virtual void dump() const { dump(stdout); }
+        virtual ~ICredResolver() {}
+    };
+
     struct SHIB_EXPORTS IAttributeRule
     {
         virtual const XMLCh* getName() const=0;
@@ -341,10 +350,13 @@ namespace shibboleth
         const IAttributeRule* m_rule;
     };
 
-    extern "C" { typedef IMetadata* MetadataFactory(const char* source); }
-    extern "C" { typedef ITrust* TrustFactory(const char* source); }
-    extern "C" { typedef ICredentials* CredentialsFactory(const char* source); }
-    extern "C" { typedef IAAP* AAPFactory(const char* source); }
+    extern "C" {
+        typedef IMetadata* MetadataFactory(const char* source);
+        typedef ITrust* TrustFactory(const char* source);
+        typedef ICredentials* CredentialsFactory(const char* source);
+        typedef ICredResolver* CredResolverFactory(const DOMElement* e);
+        typedef IAAP* AAPFactory(const char* source);
+    }
     
     class SHIB_EXPORTS ShibConfig
     {
@@ -363,6 +375,7 @@ namespace shibboleth
         virtual void regFactory(const char* type, MetadataFactory* factory)=0;
         virtual void regFactory(const char* type, TrustFactory* factory)=0;
         virtual void regFactory(const char* type, CredentialsFactory* factory)=0;
+        virtual void regFactory(const char* type, CredResolverFactory* factory)=0;
         virtual void regFactory(const char* type, AAPFactory* factory)=0;
         virtual void regFactory(const char* type, saml::SAMLAttributeFactory* factory)=0;
         virtual void unregFactory(const char* type)=0;
@@ -373,6 +386,7 @@ namespace shibboleth
         virtual saml::Iterator<IMetadata*> getMetadataProviders() const=0;
         virtual saml::Iterator<ITrust*> getTrustProviders() const=0;
         virtual saml::Iterator<ICredentials*> getCredentialProviders() const=0;
+        virtual CredResolverFactory* getCredResolverFactory(const char* type) const=0;
         virtual saml::Iterator<IAAP*> getAAPProviders() const=0;
         virtual saml::SAMLAttributeFactory* getAttributeFactory(const char* type) const=0;
     };
@@ -383,9 +397,6 @@ namespace shibboleth
         static const XMLCh SHIB_NAMEID_FORMAT_URI[];
         
         static const XMLCh XMLSIG_RETMETHOD_RAWX509[];  // DER X.509 defined by xmlsig
-        static const XMLCh SHIB_RETMETHOD_PEMX509[];    // PEM cert chain
-        static const XMLCh SHIB_RETMETHOD_DERRSA[];     // PKCS1/DER RSA private key
-        static const XMLCh SHIB_RETMETHOD_PEMRSA[];     // PEM RSA private key
         
         static saml::QName SHIB_ATTRIBUTE_VALUE_TYPE; 
     };
@@ -416,11 +427,19 @@ namespace shibboleth
             static const XMLCh OriginSite[];
             static const XMLCh SiteGroup[];
             
+            static const XMLCh CertificateRef[];
+            static const XMLCh Class[];
             static const XMLCh Credentials[];
+            static const XMLCh CustomCredResolver[];
             static const XMLCh Exponent[];
+            static const XMLCh FileCredResolver[];
+            static const XMLCh Id[];
             static const XMLCh KeyAuthority[];
+            static const XMLCh KeyRef[];
             static const XMLCh KeyUse[];
             static const XMLCh Modulus[];
+            static const XMLCh Password[];
+            static const XMLCh Path[];
             static const XMLCh RelyingParty[];
             static const XMLCh RetrievalMethod[];
             static const XMLCh RSAKeyValue[];