Add XML-based client SSL config.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Mon, 3 Nov 2003 18:27:30 +0000 (18:27 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Mon, 3 Nov 2003 18:27:30 +0000 (18:27 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@719 cb58f699-b61c-0410-a6fe-9272a202ed29

21 files changed:
schemas/shibboleth.xsd
shib-mysql-ccache/shib-mysql-ccache.cpp
shib-target/ccache-utils.h
shib-target/shib-ccache.cpp
shib-target/shib-config.cpp
shib-target/shib-resourceentry.cpp
shib-target/shibtarget.dsp
shib/Constants.cpp
shib/Makefile.am
shib/Metadata.cpp
shib/SAMLBindingFactory.cpp
shib/ShibConfig.cpp
shib/ShibPOSTProfile.cpp
shib/ShibSOAPBinding.cpp [new file with mode: 0644]
shib/XML.cpp
shib/XMLCredentials.cpp [new file with mode: 0644]
shib/XMLTrust.cpp
shib/internal.h
shib/shib-threads-win32.cpp
shib/shib.dsp
shib/shib.h

index 7bb7d08..3c84064 100644 (file)
@@ -54,6 +54,7 @@
                         <extension base="string">
                                <attribute name="Accept" type="boolean" use="optional" default="true"/>
                             <attribute name="Type" type="shib:AttributeRuleValueType" use="optional" default="literal"/>
+                            <anyAttribute namespace="##any" processContents="lax"/>
                         </extension>
                     </simpleContent>
                        </complexType>
@@ -62,6 +63,7 @@
                        <element name="AnyValue">
                                <complexType>
                                        <sequence/>
+                                       <anyAttribute namespace="##any" processContents="lax"/>
                                </complexType>
                        </element>
                    <element name="Value" maxOccurs="unbounded">
@@ -69,6 +71,7 @@
                            <simpleContent>
                                <extension base="string">
                                    <attribute name="Type" type="shib:AttributeRuleValueType" use="optional" default="literal"/>
+                                   <anyAttribute namespace="##any" processContents="lax"/>
                                </extension>
                            </simpleContent>
                        </complexType>
@@ -83,6 +86,7 @@
             <complexContent>
                 <extension base="shib:SiteRuleType">
                     <attribute name="Name" type="string" use="required"/>
+                    <anyAttribute namespace="##any" processContents="lax"/>
                 </extension>
             </complexContent>
         </complexType>
         <attribute name="Factory" type="string" use="optional"/>
         <attribute name="Alias" type="string" use="optional"/>
                <attribute name="Header" type="string" use="optional"/>
+               <anyAttribute namespace="##any" processContents="lax"/>
     </complexType>
 
     <element name="AttributeRule" type="shib:AttributeRuleType">
             <sequence>
                 <element ref="shib:AttributeRule" minOccurs="0" maxOccurs="unbounded"/>
             </sequence>
+            <anyAttribute namespace="##any" processContents="lax"/>
         </complexType>
     </element>
 
         </sequence>
         <attribute name="Name" type="string" use="required"/>
         <attribute name="ErrorURL" type="anyURI" use="optional"/>
+        <anyAttribute namespace="##any" processContents="lax"/>
     </complexType>
 
        <simpleType name="ContactTypeType">
         <sequence/>
         <attribute name="Name" type="string" use="required"/>
         <attribute name="Location" type="anyURI" use="required"/>
+        <anyAttribute namespace="##any" processContents="lax"/>
        </complexType>
 
     <complexType name="OriginSiteType">
         <attribute name="lastChanged" type="dateTime" use="optional"/>
         <attribute name="validUntil" type="dateTime" use="optional"/>
         <attribute name="cacheDuration" type="duration" use="optional"/>
-        <anyAttribute/>
+        <anyAttribute namespace="##any" processContents="lax"/>
     </complexType>    
 
     <element name="OriginSite" type="shib:OriginSiteType"/>
                                </restriction>
                        </simpleType>
                </attribute>
+               <anyAttribute namespace="##any" processContents="lax"/>
        </complexType>
        <element name="KeyAuthority" type="shib:KeyAuthorityType"/>
 
                <attribute name="lastChanged" type="dateTime" use="optional"/>
                <attribute name="validUntil" type="dateTime" use="optional"/>
                <attribute name="cacheDuration" type="duration" use="optional"/>
-               <anyAttribute/>
+               <anyAttribute namespace="##any" processContents="lax"/>
                </complexType>
        </element>
 
                        <sequence>
                                <element ref="shib:KeyUse" maxOccurs="unbounded"/>
                        </sequence>
-               <anyAttribute/>
+               <anyAttribute namespace="##any" processContents="lax"/>
                </complexType>
        </element>
        
index 3b3fb1f..e53c8ea 100644 (file)
@@ -89,8 +89,6 @@ public:
   ShibMySQLCCache();
   virtual ~ShibMySQLCCache();
 
-  virtual SAMLBinding* getBinding(const XMLCh* bindingProt)
-       { return m_cache->getBinding(bindingProt); }
   virtual CCacheEntry* find(const char* key);
   virtual void insert(const char* key, SAMLAuthenticationStatement *s,
                      const char *client_addr);
index abfa4a9..a486c9f 100644 (file)
@@ -86,8 +86,6 @@ namespace shibtarget {
   public:
     virtual ~CCache() = 0;
 
-    virtual saml::SAMLBinding* getBinding(const XMLCh* bindingProt) = 0;
-
     // insert() the Auth Statement into the CCache.
     //
     // Make sure you do not hold any open CCacheEntry objects before
index a22475a..af3a0b3 100644 (file)
@@ -149,7 +149,6 @@ public:
   InternalCCache();
   virtual ~InternalCCache();
 
-  virtual SAMLBinding* getBinding(const XMLCh* bindingProt);
   virtual CCacheEntry* find(const char* key);
   virtual void insert(const char* key, SAMLAuthenticationStatement *s,
                      const char *client_addr);
@@ -161,7 +160,6 @@ public:
 private:
   RWLock *lock;
 
-  SAMLBinding* m_SAMLBinding;
   map<string,InternalCCacheEntry*> m_hashtable;
 
   log4cpp::Category* log;
@@ -215,7 +213,6 @@ vector<SAMLAssertion*> InternalCCacheEntry::g_emptyVector;
 
 InternalCCache::InternalCCache()
 {
-  m_SAMLBinding=SAMLBindingFactory::getInstance();
   string ctx="shibtarget.InternalCCache";
   log = &(log4cpp::Category::getInstance(ctx));
   lock = RWLock::create();
@@ -232,23 +229,12 @@ InternalCCache::~InternalCCache()
   shutdown_wait->signal();
   cleanup_thread->join(NULL);
 
-  delete m_SAMLBinding;
   for (map<string,InternalCCacheEntry*>::iterator i=m_hashtable.begin(); i!=m_hashtable.end(); i++)
     delete i->second;
   delete lock;
   delete shutdown_wait;
 }
 
-SAMLBinding* InternalCCache::getBinding(const XMLCh* bindingProt)
-{
-  log->debug("looking for binding...");
-  if (!XMLString::compareString(bindingProt,SAMLBinding::SAML_SOAP_HTTPS)) {
-    log->debug("https binding found");
-    return m_SAMLBinding;
-  }
-  return NULL;
-}
-
 // assumed a lock is held..
 InternalCCacheEntry* InternalCCache::findi(const char* key)
 {
index f4562a0..29d457a 100644 (file)
@@ -188,13 +188,13 @@ void STConfig::init()
   if (ini->get_tag (app, SHIBTARGET_TAG_AACONNECTTO, true, &tag))
     samlConf.binding_defaults.conn_timeout = atoi(tag.c_str());
   if (ini->get_tag (app, SHIBTARGET_TAG_CERTFILE, true, &tag))
-    samlConf.binding_defaults.ssl_certfile = tag;
+      log.error("using OBSOLETE certfile setting, please migrate to the XML-based credential format (see the latest target deploy guide)");
   if (ini->get_tag (app, SHIBTARGET_TAG_KEYFILE, true, &tag))
-    samlConf.binding_defaults.ssl_keyfile = tag;
+      log.error("using OBSOLETE keyfile setting, please migrate to the XML-based credential format (see the latest target deploy guide)");
   if (ini->get_tag (app, SHIBTARGET_TAG_KEYPASS, true, &tag))
-    samlConf.binding_defaults.ssl_keypass = tag;
+      log.error("using OBSOLETE keypass setting, please migrate to the XML-based credential format (see the latest target deploy guide)");
   if (ini->get_tag (app, SHIBTARGET_TAG_CALIST, true, &tag))
-    samlConf.binding_defaults.ssl_calist = tag;
+      log.error("using OBSOLETE calist setting, please use the XML-based trust format (see the latest target deploy guide)");
 
   try {
     if (!samlConf.init()) {
index 9fb3408..cf60db1 100644 (file)
@@ -130,12 +130,16 @@ ResourceEntry::ResourceEntry(const Resource &resource,
   // Try this request against all the bindings in the AuthenticationStatement
   // (i.e. send it to each AA in the list of bindings)
   SAMLResponse* response = NULL;
+  OriginMetadata site(subject->getNameQualifier());
+  if (site.fail())
+      throw MetadataException("unable to locate origin site's metadata during attribute query");
+  auto_ptr<XMLCh> caller(XMLString::transcode(resource.getResource()));
+  auto_ptr<SAMLBinding> pBinding(SAMLBindingFactory::getInstance(caller.get(),site));
 
   while (!response && AAbindings.hasNext()) {
     SAMLAuthorityBinding* binding = AAbindings.next();
 
     priv->log->debug("Trying binding...");
-    SAMLBinding* pBinding=m_cache->getBinding(binding->getBinding());
     priv->log->debug("Sending request");
     response=pBinding->send(*binding,*req);
   }
index e4d1965..0dd24d9 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 wsock32.lib saml_4.lib /nologo /dll /machine:I386 /out:"Release/shibtarget_3.dll" /libpath:"../../../opensaml/c/saml/Release" /export:shibrpc_prog_1 /export:shibrpc_ping_1
+# ADD LINK32 log4cpp.lib xerces-c_2.lib xsec_lib_02.lib wsock32.lib saml_4.lib /nologo /dll /machine:I386 /out:"Release/shibtarget_4.dll" /libpath:"../../../opensaml/c/saml/Release" /export:shibrpc_prog_1 /export:shibrpc_ping_1
 # SUBTRACT LINK32 /pdb:none
 
 !ELSEIF  "$(CFG)" == "shibtarget - Win32 Debug"
@@ -80,7 +80,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 wsock32.lib saml_4D.lib /nologo /dll /debug /machine:I386 /out:"Debug/shibtarget_3D.dll" /pdbtype:sept /libpath:"../../../opensaml/c/saml/Debug" /export:shibrpc_prog_1 /export:shibrpc_ping_1
+# ADD LINK32 log4cppD.lib xerces-c_2D.lib xsec_lib_02D.lib wsock32.lib saml_4D.lib /nologo /dll /debug /machine:I386 /out:"Debug/shibtarget_4D.dll" /pdbtype:sept /libpath:"../../../opensaml/c/saml/Debug" /export:shibrpc_prog_1 /export:shibrpc_ping_1
 # SUBTRACT LINK32 /pdb:none
 
 !ENDIF 
index 15c19fd..b7a808c 100644 (file)
@@ -65,7 +65,8 @@ const XMLCh Constants::SHIB_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1
   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_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
+    chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon,
   chLatin_u, chLatin_r, chLatin_i, chNull
 };
 
@@ -74,7 +75,45 @@ const XMLCh Constants::SHIB_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nam
   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_n, chLatin_a, chLatin_m, chLatin_e, chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull
+  chLatin_n, chLatin_a, chLatin_m, chLatin_e,
+    chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull
+};
+
+const XMLCh Constants::XMLSIG_RETMETHOD_RAWX509[] = // http://www.w3.org/2000/09/xmldsig#rawX509Certificate
+{
+  chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash,
+  chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash,
+  chDigit_2, chDigit_0, chDigit_0, chDigit_0, chForwardSlash, chDigit_0, chDigit_9, chForwardSlash,
+  chLatin_x, chLatin_m, chLatin_l, chLatin_d, chLatin_s, chLatin_i, chLatin_g, chPound,
+  chLatin_r, chLatin_a, chLatin_w, 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_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);
index 2e7595e..19d1bda 100644 (file)
@@ -17,11 +17,13 @@ libshib_la_SOURCES = \
                     ShibConfig.cpp \
                     ShibPOSTProfile.cpp \
                     ShibPOSTProfileFactory.cpp \
+                    ShibSOAPBinding.cpp \
                     ScopedAttribute.cpp \
                     SimpleAttribute.cpp \
                     XML.cpp \
                     XMLMetadata.cpp \
                     XMLTrust.cpp \
+                    XMLCredentials.cpp \
                     shib-threads.cpp
 
 
index 5b35eed..d3cab8b 100644 (file)
@@ -135,12 +135,41 @@ bool Trust::validate(const ISite* site, Iterator<const XMLCh*> certs) const
     return ret;
 }
 
+bool Trust::attach(const ISite* site, SSL_CTX* ctx) const
+{
+    bool ret=false;
+    Iterator<ITrust*> it=ShibConfig::getConfig().getTrustProviders();
+    while (!ret && it.hasNext())
+    {
+        ITrust* i=it.next();
+        i->lock();
+        ret=i->attach(site,ctx);
+        i->unlock();
+    }
+    return ret;
+}
+
 Trust::~Trust()
 {
     if (m_mapper)
         m_mapper->unlock();
 }
 
+bool Credentials::attach(const XMLCh* subject, const ISite* relyingParty, SSL_CTX* ctx)
+{
+    bool ret=false;
+    Iterator<ICredentials*> it=ShibConfig::getConfig().getCredentialProviders();
+    while (!ret && it.hasNext())
+    {
+        ICredentials* i=it.next();
+        i->lock();
+        ret=i->attach(subject,relyingParty,ctx);
+        i->unlock();
+        
+    }
+    return ret;
+}
+
 AAP::AAP(const XMLCh* attrName, const XMLCh* attrNamespace) : m_mapper(NULL), m_rule(NULL)
 {
     Iterator<IAAP*> it=ShibConfig::getConfig().getAAPProviders();
index 374dff0..12aff70 100644 (file)
 using namespace shibboleth;
 using namespace saml;
 
-SAMLBinding* SAMLBindingFactory::getInstance(const XMLCh* protocol)
+SAMLBinding* SAMLBindingFactory::getInstance(const XMLCh* subject, const ISite* relyingParty, const XMLCh* protocol)
 {
     if (!protocol || XMLString::compareString(protocol,SAMLBinding::SAML_SOAP_HTTPS))
         throw UnsupportedProtocolException("SAMLBindingFactory::getInstance() unable to find binding implementation for specified protocol");
 
-    return new SAMLSOAPBinding();
+    return new ShibSOAPBinding(subject, relyingParty);
 }
index d462f5f..f86ebee 100644 (file)
@@ -90,6 +90,11 @@ 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);
@@ -118,6 +123,7 @@ bool ShibInternalConfig::init()
 
     regFactory("edu.internet2.middleware.shibboleth.metadata.XML",&XMLMetadataFactory);
     regFactory("edu.internet2.middleware.shibboleth.trust.XML",&XMLTrustFactory);
+    regFactory("edu.internet2.middleware.shibboleth.creds.XML",&XMLCredentialsFactory);
     regFactory("edu.internet2.middleware.shibboleth.target.AAP.XML",&XMLAAPFactory);
     regFactory("edu.internet2.middleware.shibboleth.target.AttributeFactory",&ShibAttributeFactory);
 
@@ -130,8 +136,10 @@ void ShibInternalConfig::term()
         delete *i;
     for (vector<ITrust*>::iterator j=m_trust_providers.begin(); j!=m_trust_providers.end(); j++)
         delete *j;
-    for (vector<IAAP*>::iterator k=m_aap_providers.begin(); k!=m_aap_providers.end(); k++)
+    for (vector<ICredentials*>::iterator k=m_cred_providers.begin(); k!=m_cred_providers.end(); k++)
         delete *k;
+    for (vector<IAAP*>::iterator l=m_aap_providers.begin(); l!=m_aap_providers.end(); l++)
+        delete *l;
 }
 
 void ShibInternalConfig::regFactory(const char* type, MetadataFactory* factory)
@@ -146,6 +154,15 @@ void ShibInternalConfig::regFactory(const char* type, TrustFactory* factory)
         m_trustFactoryMap[type]=factory;
 }
 
+void ShibInternalConfig::regFactory(const char* type, CredentialsFactory* factory)
+{
+    if (type && factory)
+    {
+        m_credFactoryMap[type]=factory;
+        SAMLConfig::getConfig().binding_defaults.ssl_ctx_callback=ssl_ctx_callback;
+    }
+}
+
 void ShibInternalConfig::regFactory(const char* type, AAPFactory* factory)
 {
     if (type && factory)
@@ -164,6 +181,7 @@ void ShibInternalConfig::unregFactory(const char* type)
     {
         m_metadataFactoryMap.erase(type);
         m_trustFactoryMap.erase(type);
+        m_credFactoryMap.erase(type);
         m_aapFactoryMap.erase(type);
     }
 }
@@ -204,14 +222,23 @@ bool ShibInternalConfig::addMetadata(const char* type, const char* source)
             }
             else
             {
-                AAPFactoryMap::const_iterator k=m_aapFactoryMap.find(type);
-                if (k!=m_aapFactoryMap.end())
+                CredentialsFactoryMap::const_iterator k=m_credFactoryMap.find(type);
+                if (k!=m_credFactoryMap.end())
                 {
-                    m_aap_providers.push_back((k->second)(source));
+                    m_cred_providers.push_back((k->second)(source));
                     ret=true;
                 }
                 else
-                    throw MetadataException("ShibConfig::addMetadata() unable to locate a metadata factory of the requested type");
+                {
+                    AAPFactoryMap::const_iterator l=m_aapFactoryMap.find(type);
+                    if (l!=m_aapFactoryMap.end())
+                    {
+                        m_aap_providers.push_back((l->second)(source));
+                        ret=true;
+                    }
+                    else
+                        throw MetadataException("ShibConfig::addMetadata() unable to locate a metadata factory of the requested type");
+                }
             }
         }
     }
index 52abc00..2091d77 100644 (file)
@@ -176,13 +176,14 @@ SAMLResponse* ShibPOSTProfile::accept(const XMLByte* buf, XMLCh** originSitePtr)
 
     Trust t;
     Iterator<XSECCryptoX509*> certs=t.getCertificates(hs->getName());
+    Iterator<XSECCryptoX509*> certs2=t.getCertificates(originSite);
 
     // Signature verification now takes place. We check the assertion and the response.
     // Assertion signing is optional, response signing is mandatory.
     bool bVerified=false;
     if (assertion->isSigned())
     {
-        while (certs.hasNext())
+        while (!bVerified && certs.hasNext())
         {
             try {
                 verifySignature(*assertion, mapper, handleService, certs.next()->clonePublicKey());
@@ -192,12 +193,22 @@ SAMLResponse* ShibPOSTProfile::accept(const XMLByte* buf, XMLCh** originSitePtr)
                 // continue trying others
             }
         }
+        while (!bVerified && certs2.hasNext())
+        {
+            try {
+                verifySignature(*assertion, mapper, handleService, certs2.next()->clonePublicKey());
+                bVerified=true;
+            }
+            catch (InvalidCryptoException&) {
+                // continue trying others
+            }
+        }
         if (!bVerified)
             verifySignature(*assertion, mapper, handleService);
     }
 
     bVerified=false;
-    while (certs.hasNext())
+    while (!bVerified && certs.hasNext())
     {
         try {
             verifySignature(*r, mapper, handleService, certs.next()->clonePublicKey());
@@ -207,6 +218,16 @@ SAMLResponse* ShibPOSTProfile::accept(const XMLByte* buf, XMLCh** originSitePtr)
             // continue trying others
         }
     }
+    while (!bVerified && certs2.hasNext())
+    {
+        try {
+            verifySignature(*r, mapper, handleService, certs2.next()->clonePublicKey());
+            bVerified=true;
+        }
+        catch (InvalidCryptoException&) {
+            // continue trying others
+        }
+    }
     if (!bVerified)
         verifySignature(*r, mapper, handleService);
 
diff --git a/shib/ShibSOAPBinding.cpp b/shib/ShibSOAPBinding.cpp
new file mode 100644 (file)
index 0000000..72cb63b
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+
+/* ShibSOAPBinding.cpp - Shibboleth version of SOAP Binding with SSL callback
+
+   Scott Cantor
+   10/30/03
+   
+   $History:$
+*/
+
+#include "internal.h"
+
+#include <log4cpp/Category.hh>
+
+using namespace std;
+using namespace log4cpp;
+using namespace shibboleth;
+using namespace saml;
+
+SAMLResponse* ShibSOAPBinding::send(const SAMLAuthorityBinding& bindingInfo, SAMLRequest& req, SAMLConfig::SAMLBindingConfig& conf)
+{
+    conf.ssl_ctx_callback=ssl_ctx_callback;
+    conf.ssl_ctx_data=this;
+    
+    return SAMLSOAPBinding::send(bindingInfo, req, conf);
+}
+
+bool shibboleth::ssl_ctx_callback(void* ssl_ctx, void* userptr)
+{
+    try
+    {
+        ShibSOAPBinding* b = reinterpret_cast<ShibSOAPBinding*>(userptr);
+        if (!Credentials::attach(b->m_subject, b->m_relyingParty, reinterpret_cast<ssl_ctx_st*>(ssl_ctx)))
+        {
+            NDC("ssl_ctx_callback");
+            Category::getInstance(SHIB_LOGCAT".ShibSOAPBinding").warn("found no appropriate credentials to attach, request will be anonymous");
+        }
+
+        Trust t;
+        if (!t.attach(b->m_relyingParty, reinterpret_cast<ssl_ctx_st*>(ssl_ctx)))
+        {
+            NDC("ssl_ctx_callback");
+            Category::getInstance(SHIB_LOGCAT".ShibSOAPBinding").warn("found no appropriate authorities to attach, request will be unverified");
+        }
+    }
+    catch (SAMLException& e)
+    {
+        NDC("ssl_ctx_callback");
+        Category::getInstance(SHIB_LOGCAT".ShibSOAPBinding").error(string("caught a SAML exception while attaching credentials to request: ") + e.what());
+        return false;
+    }
+    catch (...)
+    {
+        NDC("ssl_ctx_callback");
+        Category::getInstance(SHIB_LOGCAT".ShibSOAPBinding").error("caught an unknown exception while attaching credentials to request: ");
+        return false;
+    }
+
+    return true;
+}
index c4f2312..47f4778 100644 (file)
@@ -121,13 +121,42 @@ 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::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::Exponent[] =
+{ chLatin_E, chLatin_x, chLatin_p, chLatin_o, chLatin_n, chLatin_e, chLatin_n, chLatin_t, 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::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::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 };
+
+const XMLCh XML::Literals::RetrievalMethod[] =
+{ chLatin_R, chLatin_e, chLatin_t, chLatin_r, chLatin_i, chLatin_e, chLatin_v, chLatin_a, chLatin_l,
+  chLatin_M, chLatin_e, chLatin_t, chLatin_h, chLatin_o, chLatin_d, chNull };
+
+const XMLCh XML::Literals::RSAKeyValue[] =
+{ chLatin_R, chLatin_S, chLatin_A, chLatin_K, chLatin_e, chLatin_y, chLatin_V, chLatin_a, chLatin_l, chLatin_u, chLatin_e, chNull };
+
 const XMLCh XML::Literals::Trust[] =
 { chLatin_T, chLatin_r, chLatin_u, chLatin_s, chLatin_t, chNull };
 
+const XMLCh XML::Literals::URI[] =
+{ chLatin_U, chLatin_R, chLatin_I, chNull };
+
+const XMLCh XML::Literals::VerifyDepth[] =
+{ chLatin_V, chLatin_e, chLatin_r, chLatin_i, chLatin_f, chLatin_y, chLatin_D, chLatin_e, chLatin_p, chLatin_t, chLatin_h, chNull };
+
 const XMLCh XML::Literals::Accept[]=
 { chLatin_A, chLatin_c, chLatin_c, chLatin_e, chLatin_p, chLatin_t, chNull };
 
diff --git a/shib/XMLCredentials.cpp b/shib/XMLCredentials.cpp
new file mode 100644 (file)
index 0000000..11166de
--- /dev/null
@@ -0,0 +1,552 @@
+/* 
+ * 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.
+ */
+
+/* XMLTrust.h - a trust implementation that uses an XML file
+
+   Scott Cantor
+   9/27/02
+
+   $History:$
+*/
+
+#include "internal.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <log4cpp/Category.hh>
+#include <xercesc/framework/URLInputSource.hpp>
+#include <xercesc/util/regx/RegularExpression.hpp>
+#include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
+
+using namespace shibboleth;
+using namespace saml;
+using namespace log4cpp;
+using namespace std;
+
+class shibboleth::XMLCredentialsImpl
+{
+public:
+    XMLCredentialsImpl(const char* pathname);
+    ~XMLCredentialsImpl();
+    
+    struct KeyUse
+    {
+        KeyUse() {}
+        ~KeyUse();
+
+        bool attach(SSL_CTX* ctx);
+        
+        enum format_t { X509DATA, DER, PEM };
+        
+        format_t m_certtype, m_keytype;
+        vector<X509*> m_certs;
+        string m_certfile, m_keyfile;
+        vector<pair<const XMLCh*,bool> > m_relying;
+    };
+    
+    vector<KeyUse*> m_keyuses;
+    typedef multimap<pair<const XMLCh*,bool>,KeyUse*> BindingMap;
+    BindingMap m_bindings;
+    
+    DOMDocument* m_doc;
+};
+
+XMLCredentialsImpl::KeyUse::~KeyUse()
+{
+    for (vector<X509*>::iterator i=m_certs.begin(); i!=m_certs.end(); i++)
+        X509_free(*i);
+}
+
+bool XMLCredentialsImpl::KeyUse::attach(SSL_CTX* ctx)
+{
+    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");
+                    }
+                }
+            }
+    }
+    
+    switch (m_keytype)
+    {
+        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");
+            }
+    }
+    
+    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)
+{
+    NDC ndc("XMLCredentialsImpl");
+    Category& log=Category::getInstance(SHIB_LOGCAT".XMLCredentialsImpl");
+
+    saml::XML::Parser p;
+    try
+    {
+        static XMLCh base[]={chLatin_f, chLatin_i, chLatin_l, chLatin_e, chColon, chForwardSlash, chForwardSlash, chForwardSlash, chNull};
+        URLInputSource src(base,pathname);
+        Wrapper4InputSource dsrc(&src,false);
+        m_doc=p.parse(dsrc);
+
+        log.infoStream() << "Loaded and parsed creds file (" << pathname << ")" << CategoryStream::ENDLINE;
+
+        DOMElement* e = m_doc->getDocumentElement();
+        if (XMLString::compareString(XML::SHIB_NS,e->getNamespaceURI()) ||
+            XMLString::compareString(SHIB_L(Credentials),e->getLocalName()))
+        {
+            log.error("Construction requires a valid creds file: (shib:Credentials as root element)");
+            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++)
+        {
+            auto_ptr<KeyUse> ku(new KeyUse());
+
+            bool key=false,cert=false;
+            
+            // 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++)
+            {
+                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;
+                }
+            }
+            
+            if (!cert)
+            {
+                // Is there an X509Data?
+                DOMNodeList* x509data=static_cast<DOMElement*>(nlist->item(i))->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, 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");
+                }
+            }
+            
+            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;
+            }
+            
+            // Pull in the relying parties.
+            DOMNodeList* parties=static_cast<DOMElement*>(nlist->item(i))->getElementsByTagNameNS(XML::SHIB_NS,SHIB_L(RelyingParty));
+            int m=0;
+            while (parties && m<parties->getLength())
+            {
+                const XMLCh* name=parties->item(m)->getFirstChild()->getNodeValue();
+                if (name && *name)
+                {
+                    static const XMLCh one[]={ chDigit_1, chNull };
+                    static const XMLCh tru[]={ chLatin_t, chLatin_r, chLatin_u, chLatin_e, chNull };
+                    const XMLCh* regexp=
+                        static_cast<DOMElement*>(parties->item(m))->getAttributeNS(NULL,SHIB_L(regexp));
+                    bool flag=(!XMLString::compareString(regexp,one) || !XMLString::compareString(regexp,tru));
+                    ku->m_relying.push_back(pair<const XMLCh*,bool>(name,flag));
+                }
+                m++;
+            }
+            // If no RelyingParties, this is a catch-all binding.
+            if (m==0)
+                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));
+            int l=0;
+            while (subs && l<subs->getLength())
+            {
+                const XMLCh* name=subs->item(l)->getFirstChild()->getNodeValue();
+                if (name && *name)
+                {
+                    static const XMLCh one[]={ chDigit_1, chNull };
+                    static const XMLCh tru[]={ chLatin_t, chLatin_r, chLatin_u, chLatin_e, chNull };
+                    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()));
+                }
+                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_keyuses.push_back(ku.release());
+        }
+    }
+    catch (SAMLException& e)
+    {
+        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);
+        if (m_doc)
+            m_doc->release();
+        throw;
+    }
+    catch (...)
+    {
+        log.error("Unexpected error while parsing creds configuration");
+        for (vector<KeyUse*>::iterator i=m_keyuses.begin(); i!=m_keyuses.end(); i++)
+            delete (*i);
+        if (m_doc)
+            m_doc->release();
+        throw;
+    }
+}
+
+XMLCredentialsImpl::~XMLCredentialsImpl()
+{
+    for (vector<KeyUse*>::iterator i=m_keyuses.begin(); i!=m_keyuses.end(); i++)
+        delete (*i);
+    if (m_doc)
+        m_doc->release();
+}
+
+XMLCredentials::XMLCredentials(const char* pathname) : m_filestamp(0), m_source(pathname), m_impl(NULL)
+{
+#ifdef WIN32
+    struct _stat stat_buf;
+    if (_stat(pathname, &stat_buf) == 0)
+#else
+    struct stat stat_buf;
+    if (stat(pathname, &stat_buf) == 0)
+#endif
+        m_filestamp=stat_buf.st_mtime;
+    m_impl=new XMLCredentialsImpl(pathname);
+    m_lock=RWLock::create();
+}
+
+XMLCredentials::~XMLCredentials()
+{
+    delete m_lock;
+    delete m_impl;
+}
+
+void XMLCredentials::lock()
+{
+    m_lock->rdlock();
+
+    // Check if we need to refresh.
+#ifdef WIN32
+    struct _stat stat_buf;
+    if (_stat(m_source.c_str(), &stat_buf) == 0)
+#else
+    struct stat stat_buf;
+    if (stat(m_source.c_str(), &stat_buf) == 0)
+#endif
+    {
+        if (m_filestamp>0 && m_filestamp<stat_buf.st_mtime)
+        {
+            // Elevate lock and recheck.
+            m_lock->unlock();
+            m_lock->wrlock();
+            if (m_filestamp>0 && m_filestamp<stat_buf.st_mtime)
+            {
+                try
+                {
+                    XMLCredentialsImpl* new_mapper=new XMLCredentialsImpl(m_source.c_str());
+                    delete m_impl;
+                    m_impl=new_mapper;
+                    m_filestamp=stat_buf.st_mtime;
+                    m_lock->unlock();
+                }
+                catch(SAMLException& e)
+                {
+                    m_lock->unlock();
+                    saml::NDC ndc("lock");
+                    Category::getInstance(SHIB_LOGCAT".XMLCredentials").error("failed to reload credentials metadata, sticking with what we have: %s", e.what());
+                }
+                catch(...)
+                {
+                    m_lock->unlock();
+                    saml::NDC ndc("lock");
+                    Category::getInstance(SHIB_LOGCAT".XMLCredentials").error("caught an unknown exception, sticking with what we have");
+                }
+            }
+            else
+            {
+                m_lock->unlock();
+            }
+            m_lock->rdlock();
+        }
+    }
+}
+
+void XMLCredentials::unlock()
+{
+    m_lock->unlock();
+}
+
+
+bool XMLCredentials::attach(const XMLCh* subject, const ISite* relyingParty, SSL_CTX* ctx) const
+{
+    NDC ndc("attach");
+
+    // Use the matching bindings.
+    for (XMLCredentialsImpl::BindingMap::const_iterator i=m_impl->m_bindings.begin(); i!=m_impl->m_bindings.end(); i++)
+    {
+        bool match=false;
+        
+        if (i->first.first==NULL)   // catch-all entry
+        {
+            match=true;
+        }
+        else if (i->first.second)   // regexp
+        {
+            try
+            {
+                RegularExpression re(i->first.first);
+                if (re.matches(subject))
+                    match=true;
+            }
+            catch (XMLException& ex)
+            {
+                auto_ptr<char> tmp(XMLString::transcode(ex.getMessage()));
+                Category& log=Category::getInstance(SHIB_LOGCAT".XMLCredentials");
+                log.errorStream() << "caught exception while parsing regular expression: " << tmp.get()
+                    << CategoryStream::ENDLINE;
+            }
+        }
+        else if (!XMLString::compareString(subject,i->first.first))
+        {
+            match=true;
+        }
+        
+        if (match)
+        {
+            // See if the relying party applies...
+            match=false;
+            for (vector<pair<const XMLCh*,bool> >::const_iterator j=i->second->m_relying.begin(); j!=i->second->m_relying.end(); j++)
+            {
+                if (j->first==NULL)     // catch-all entry
+                {
+                    match=true;
+                }
+                else if (j->second)     // regexp
+                {
+                    try
+                    {
+                        RegularExpression re(j->first);
+                        if (re.matches(relyingParty->getName()))
+                            match=true;
+                        else
+                        {
+                            Iterator<const XMLCh*> groups=relyingParty->getGroups();
+                            while (!match && groups.hasNext())
+                                if (re.matches(groups.next()))
+                                    match=true;
+                        }
+                    }
+                    catch (XMLException& ex)
+                    {
+                        auto_ptr<char> tmp(XMLString::transcode(ex.getMessage()));
+                        Category& log=Category::getInstance(SHIB_LOGCAT".XMLCredentials");
+                        log.errorStream() << "caught exception while parsing regular expression: " << tmp.get()
+                            << CategoryStream::ENDLINE;
+                    }
+                }
+                else if (!XMLString::compareString(relyingParty->getName(),j->first))
+                {
+                    match=true;
+                }
+                else
+                {
+                    Iterator<const XMLCh*> groups=relyingParty->getGroups();
+                    while (!match && groups.hasNext())
+                        if (!XMLString::compareString(groups.next(),j->first))
+                            match=true;
+                }
+            }
+        }
+        
+        if (match)
+        {
+            // We have the credentials to use...
+            return i->second->attach(ctx);
+        }
+    }
+
+    return false;
+}
index 4f37c66..711af5f 100644 (file)
@@ -88,12 +88,15 @@ public:
     
     struct KeyAuthority
     {
-        KeyAuthority() : m_store(NULL) {}
+        KeyAuthority() : m_store(NULL), m_depth(0), m_type(authority) {}
         ~KeyAuthority();
-        X509_STORE* getX509Store();
+        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;
     };
     
     vector<KeyAuthority*> m_keyauths;
@@ -103,57 +106,63 @@ public:
     DOMDocument* m_doc;
 };
 
-X509_STORE* XMLTrustImpl::KeyAuthority::getX509Store()
+X509_STORE* XMLTrustImpl::KeyAuthority::getX509Store(bool cached)
 {
     // We cache them once they're built...
-    if (m_store)
+    if (m_store && cached)
         return m_store;
-
+    
     NDC ndc("getX509Store");
+    Category& log=Category::getInstance(SHIB_LOGCAT".XMLTrust");
 
-    // Load the cert vector into a store.
+    // Do we need to convert to native cert format?
+    if (m_nativecerts.empty())
+    {
+        for (vector<XSECCryptoX509*>::const_iterator i=m_certs.begin(); i!=m_certs.end(); i++)
+        {
+            X509* x509=B64_to_X509((*i)->getDEREncodingSB().rawCharBuffer());
+            if (!x509)
+            {
+                log.warn("failed to parse X509 buffer: %s", (*i)->getDEREncodingSB().rawCharBuffer());
+                continue;
+            }
+            m_nativecerts.push_back(x509);
+        }
+    }
     
-    if (!(m_store=X509_STORE_new()))
+    // Load the cert vector into a store.
+    X509_STORE* store=NULL;
+    if (!(store=X509_STORE_new()))
     {
         log_openssl();
         return NULL;
     }
     
-    X509_STORE_set_verify_cb_func(m_store,verify_callback);
+    X509_STORE_set_verify_cb_func(store,verify_callback);
 
-    Category& log=Category::getInstance(SHIB_LOGCAT".XMLTrustImpl");
-
-    for (vector<XSECCryptoX509*>::const_iterator i=m_certs.begin(); i!=m_certs.end(); i++)
+    for (vector<X509*>::iterator j=m_nativecerts.begin(); j!=m_nativecerts.end(); j++)
     {
-        X509* x509=B64_to_X509((*i)->getDEREncodingSB().rawCharBuffer());
-        if (!x509)
-        {
-           //X509_STORE_free(m_store);
-            //return m_store=NULL;
-           log.warn("failed to parse X509 buffer: %s",
-                    (*i)->getDEREncodingSB().rawCharBuffer());
-           continue;
-        }
-
-        if (!X509_STORE_add_cert(m_store,x509))
+        if (!X509_STORE_add_cert(store,X509_dup(*j)))
         {
             log_openssl();
-           log.warn("failed to add cert: %s", x509->name);
-            X509_free(x509);
-            //X509_STORE_free(m_store);
-            //return m_store=NULL;
-           continue;
+            log.warn("failed to add cert: %s", (*j)->name);
+            continue;
         }
     }
 
-    return m_store;
+    if (cached)
+        m_store=store;
+    return store;
 }
 
 XMLTrustImpl::KeyAuthority::~KeyAuthority()
 {
-    for (vector<XSECCryptoX509*>::iterator i=m_certs.begin(); i!=m_certs.end(); i++)
-        delete (*i);
-    X509_STORE_free(m_store);
+    if (m_store)
+        X509_STORE_free(m_store);
+    for (vector<X509*>::iterator i=m_nativecerts.begin(); i!=m_nativecerts.end(); i++)
+        X509_free(*i);
+    for (vector<XSECCryptoX509*>::iterator j=m_certs.begin(); j!=m_certs.end(); j++)
+        delete (*j);
 }
 
 XMLTrustImpl::XMLTrustImpl(const char* pathname) : m_doc(NULL)
@@ -173,19 +182,27 @@ XMLTrustImpl::XMLTrustImpl(const char* pathname) : m_doc(NULL)
 
         DOMElement* e = m_doc->getDocumentElement();
         if (XMLString::compareString(XML::SHIB_NS,e->getNamespaceURI()) ||
-            XMLString::compareString(XML::Literals::Trust,e->getLocalName()))
+            XMLString::compareString(SHIB_L(Trust),e->getLocalName()))
         {
             log.error("Construction requires a valid trust file: (shib:Trust as root element)");
             throw MetadataException("Construction requires a valid trust file: (shib:Trust as root element)");
         }
 
         // Loop over the KeyAuthority elements.
-        DOMNodeList* nlist=e->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::KeyAuthority);
+        DOMNodeList* nlist=e->getElementsByTagNameNS(XML::SHIB_NS,SHIB_L(KeyAuthority));
         for (int i=0; nlist && i<nlist->getLength(); i++)
         {
             KeyAuthority* ka=new KeyAuthority();
             m_keyauths.push_back(ka);
             
+            const XMLCh* depth=static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIB_L(VerifyDepth));
+            if (depth && *depth)
+                ka->m_depth=XMLString::parseInt(depth);
+            
+            const XMLCh* type=static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,SHIB_L(Type));
+            if (type && *type==chLatin_e)
+                ka->m_type=KeyAuthority::entity;
+
             // Very rudimentary, grab up all the X509Certificate elements, and flatten into one list.
             DOMNodeList* certlist=static_cast<DOMElement*>(nlist->item(i))->getElementsByTagNameNS(
                 saml::XML::XMLSIG_NS,L(X509Certificate)
@@ -200,7 +217,8 @@ XMLTrustImpl::XMLTrustImpl(const char* pathname) : m_doc(NULL)
             
             // Now map the subjects to the list of certs.
             DOMNodeList* subs=static_cast<DOMElement*>(nlist->item(i))->getElementsByTagNameNS(XML::SHIB_NS,L(Subject));
-            for (int k=0; subs && k<subs->getLength(); k++)
+            int k=0;
+            while (subs && k<subs->getLength())
             {
                 const XMLCh* name=subs->item(k)->getFirstChild()->getNodeValue();
                 if (name && *name)
@@ -208,16 +226,20 @@ XMLTrustImpl::XMLTrustImpl(const char* pathname) : m_doc(NULL)
                     static const XMLCh one[]={ chDigit_1, chNull };
                     static const XMLCh tru[]={ chLatin_t, chLatin_r, chLatin_u, chLatin_e, chNull };
                     const XMLCh* regexp=
-                        static_cast<DOMElement*>(subs->item(k))->getAttributeNS(NULL,XML::Literals::regexp);
+                        static_cast<DOMElement*>(subs->item(k))->getAttributeNS(NULL,SHIB_L(regexp));
                     bool flag=(!XMLString::compareString(regexp,one) || !XMLString::compareString(regexp,tru));
                     m_bindings[pair<const XMLCh*,bool>(name,flag)]=ka;
                 }
+                k++;
             }
+            // If no Subjects, this is a catch-all binding.
+            if (k==0)
+                m_bindings[pair<const XMLCh*,bool>(NULL,false)]=ka;
         }
     }
     catch (SAMLException& e)
     {
-        log.errorStream() << "XML error while parsing site configuration: " << e.what() << CategoryStream::ENDLINE;
+        log.errorStream() << "XML error while parsing trust configuration: " << e.what() << CategoryStream::ENDLINE;
         for (vector<KeyAuthority*>::iterator i=m_keyauths.begin(); i!=m_keyauths.end(); i++)
             delete (*i);
         if (m_doc)
@@ -226,7 +248,7 @@ XMLTrustImpl::XMLTrustImpl(const char* pathname) : m_doc(NULL)
     }
     catch (...)
     {
-        log.error("Unexpected error while parsing site configuration");
+        log.error("Unexpected error while parsing trust configuration");
         for (vector<KeyAuthority*>::iterator i=m_keyauths.begin(); i!=m_keyauths.end(); i++)
             delete (*i);
         if (m_doc)
@@ -297,12 +319,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
             {
@@ -320,10 +342,17 @@ void XMLTrust::unlock()
 
 Iterator<XSECCryptoX509*> XMLTrust::getCertificates(const XMLCh* subject) const
 {
-    // Find the first matching binding.
+    // Find the first matching entity binding.
     for (XMLTrustImpl::BindingMap::const_iterator i=m_impl->m_bindings.begin(); i!=m_impl->m_bindings.end(); i++)
     {
-        if (i->first.second)   // regexp
+        if (i->second->m_type!=XMLTrustImpl::KeyAuthority::entity)
+            continue;
+            
+        if (i->first.first==NULL)   // catch-all entry
+        {
+            return i->second->m_certs;
+        }
+        else if (i->first.second)   // regexp
         {
             try
             {
@@ -340,7 +369,7 @@ Iterator<XSECCryptoX509*> XMLTrust::getCertificates(const XMLCh* subject) const
                     << CategoryStream::ENDLINE;
             }
         }
-        else if (!XMLString::compareString(subject,i->first.first))
+        else if (!XMLString::compareString(subject,i->first.first))     // exact match
         {
             return i->second->m_certs;
         }
@@ -348,6 +377,72 @@ Iterator<XSECCryptoX509*> XMLTrust::getCertificates(const XMLCh* subject) const
     return EMPTY(XSECCryptoX509*);
 }
 
+bool XMLTrust::attach(const ISite* site, SSL_CTX* ctx) const
+{
+    NDC ndc("attach");
+
+    // Use the matching bindings.
+    for (XMLTrustImpl::BindingMap::const_iterator i=m_impl->m_bindings.begin(); i!=m_impl->m_bindings.end(); i++)
+    {
+        if (i->second->m_type!=XMLTrustImpl::KeyAuthority::authority)
+            continue;
+
+        bool match=false;
+        if (i->first.first==NULL)   // catch-all entry
+        {
+            match=true;
+        }
+        else if (i->first.second)   // regexp
+        {
+            try
+            {
+                RegularExpression re(i->first.first);
+                if (re.matches(site->getName()))
+                    match=true;
+                else
+                {
+                    Iterator<const XMLCh*> groups=site->getGroups();
+                    while (!match && groups.hasNext())
+                        if (re.matches(groups.next()))
+                            match=true;
+                }
+            }
+            catch (XMLException& ex)
+            {
+                auto_ptr<char> tmp(XMLString::transcode(ex.getMessage()));
+                Category& log=Category::getInstance(SHIB_LOGCAT".XMLTrust");
+                log.errorStream() << "caught exception while parsing regular expression: " << tmp.get()
+                    << CategoryStream::ENDLINE;
+            }
+        }
+        else if (!XMLString::compareString(site->getName(),i->first.first))     // exact match
+        {
+            match=true;
+        }
+        else
+        {
+            Iterator<const XMLCh*> groups=site->getGroups();
+            while (!match && groups.hasNext())
+                if (!XMLString::compareString(i->first.first,groups.next()))
+                    match=true;
+        }
+
+        // If we have a match, use the associated keyauth and load it into the context's store.
+        if (match)
+        {
+            X509_STORE* store=i->second->getX509Store(false);
+            if (store)
+            {
+                SSL_CTX_set_cert_store(ctx,store);
+                SSL_CTX_set_verify_depth(ctx,i->second->m_depth);
+            }
+            return true;
+        }
+    }
+
+    return false;
+}
+
 bool XMLTrust::validate(const ISite* site, Iterator<XSECCryptoX509*> certs) const
 {
     vector<const XMLCh*> temp;
@@ -376,8 +471,15 @@ bool XMLTrust::validate(const ISite* site, Iterator<const XMLCh*> certs) const
     // Use the matching bindings.
     for (XMLTrustImpl::BindingMap::const_iterator i=m_impl->m_bindings.begin(); i!=m_impl->m_bindings.end(); i++)
     {
+        if (i->second->m_type!=XMLTrustImpl::KeyAuthority::authority)
+            continue;
+
         bool match=false;
-        if (i->first.second)   // regexp
+        if (i->first.first==NULL)   // catch-all entry
+        {
+            match=true;
+        }
+        else if (i->first.second)   // regexp
         {
             try
             {
@@ -395,13 +497,12 @@ bool XMLTrust::validate(const ISite* site, Iterator<const XMLCh*> certs) const
             catch (XMLException& ex)
             {
                 auto_ptr<char> tmp(XMLString::transcode(ex.getMessage()));
-                NDC ndc("getCertificates");
                 Category& log=Category::getInstance(SHIB_LOGCAT".XMLTrust");
                 log.errorStream() << "caught exception while parsing regular expression: " << tmp.get()
                     << CategoryStream::ENDLINE;
             }
         }
-        else if (!XMLString::compareString(site->getName(),i->first.first))
+        else if (!XMLString::compareString(site->getName(),i->first.first))     // exact match
         {
             match=true;
         }
@@ -436,6 +537,8 @@ bool XMLTrust::validate(const ISite* site, Iterator<const XMLCh*> certs) const
 #else
                 X509_STORE_CTX_init(ctx,store,sk_X509_value(chain,0),chain);
 #endif
+                if (i->second->m_depth)
+                    X509_STORE_CTX_set_depth(ctx,i->second->m_depth);
                 if (X509_verify_cert(ctx)==1)
                 {
                     sk_X509_pop_free(chain,X509_free);
index b798ec8..b84850a 100644 (file)
 #include "shib.h"
 #include "shib-threads.h"
 
+#include <openssl/x509.h>
+
 #define SHIB_LOGCAT "Shibboleth"
 
 namespace shibboleth
 {
     class XMLMetadataImpl;
-    class SHIB_EXPORTS XMLMetadata : public IMetadata
+    class XMLMetadata : public IMetadata
     {
     public:
         XMLMetadata(const char* pathname);
@@ -96,7 +98,7 @@ namespace shibboleth
     };
 
     class XMLTrustImpl;
-    class SHIB_EXPORTS XMLTrust : public ITrust
+    class XMLTrust : public ITrust
     {
     public:
         XMLTrust(const char* pathname);
@@ -107,6 +109,7 @@ namespace shibboleth
         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;
@@ -115,8 +118,25 @@ namespace shibboleth
         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 SHIB_EXPORTS XMLAAP : public IAAP
+    class XMLAAP : public IAAP
     {
     public:
         XMLAAP(const char* pathname);
@@ -135,6 +155,53 @@ namespace shibboleth
         XMLAAPImpl* m_impl;
     };
     
+    class ClubShibPOSTProfile : public ShibPOSTProfile
+    {
+    public:
+        ClubShibPOSTProfile(const saml::Iterator<const XMLCh*>& policies, const XMLCh* receiver, int ttlSeconds);
+        ClubShibPOSTProfile(const saml::Iterator<const XMLCh*>& policies, const XMLCh* issuer);
+        virtual ~ClubShibPOSTProfile();
+
+        virtual saml::SAMLResponse* prepare(
+            const XMLCh* recipient,
+            const XMLCh* name,
+            const XMLCh* nameQualifier,
+            const XMLCh* subjectIP,
+            const XMLCh* authMethod,
+            time_t authInstant,
+            const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings,
+            XSECCryptoKey* responseKey,
+            const saml::Iterator<XSECCryptoX509*>& responseCerts=EMPTY(XSECCryptoX509*),
+            XSECCryptoKey* assertionKey=NULL,
+            const saml::Iterator<XSECCryptoX509*>& assertionCerts=EMPTY(XSECCryptoX509*)
+            );
+
+    protected:
+        virtual void verifySignature(
+            const saml::SAMLSignedObject& obj,
+            const IOriginSite* originSite,
+            const XMLCh* signerName,
+            XSECCryptoKey* knownKey=NULL);
+    };
+    
+    class ShibSOAPBinding : public saml::SAMLSOAPBinding
+    {
+    public:
+        ShibSOAPBinding(const XMLCh* subject, const ISite* relyingParty) : m_subject(subject), m_relyingParty(relyingParty) {}
+        virtual ~ShibSOAPBinding() {}
+
+        virtual saml::SAMLResponse* send(
+            const saml::SAMLAuthorityBinding& bindingInfo,
+            saml::SAMLRequest& req,
+            saml::SAMLConfig::SAMLBindingConfig& conf=saml::SAMLConfig::getConfig().binding_defaults
+            );
+
+    private:
+        friend bool ssl_ctx_callback(void* ssl_ctx, void* userptr);
+        const XMLCh* m_subject;
+        const ISite* m_relyingParty;
+    };
+
     class ShibInternalConfig : public ShibConfig
     {
     public:
@@ -145,6 +212,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, AAPFactory* factory);
         void regFactory(const char* type, saml::SAMLAttributeFactory* factory);
         void unregFactory(const char* type);
@@ -153,26 +221,42 @@ 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;}
         saml::Iterator<IAAP*> getAAPProviders() const {return m_aap_providers;}
         saml::SAMLAttributeFactory* getAttributeFactory(const char* type) const;
 
     private:
         friend class OriginMetadata;
         friend class Trust;
+        friend class Credentials;
         friend class AAP;
         
         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, AAPFactory*> AAPFactoryMap;
         typedef std::map<std::string, saml::SAMLAttributeFactory*> AttributeFactoryMap;
         MetadataFactoryMap m_metadataFactoryMap;
         TrustFactoryMap m_trustFactoryMap;
+        CredentialsFactoryMap m_credFactoryMap;
         AAPFactoryMap m_aapFactoryMap;
         AttributeFactoryMap m_attrFactoryMap;
         std::vector<IMetadata*> m_providers;
         std::vector<ITrust*> m_trust_providers;
+        std::vector<ICredentials*> m_cred_providers;
         std::vector<IAAP*> m_aap_providers;
     };
+
+    // OpenSSL Utilities
+    
+    // Custom metadata-driven SSL context callback
+    bool ssl_ctx_callback(void* ssl_ctx, void* userptr);
+    
+    // Log errors from OpenSSL error queue
+    void log_openssl();
+
+    // build an OpenSSL cert out of a base-64 encoded DER buffer (XML style)
+    X509* B64_to_X509(const char* buf);
 }
 
 #endif
index 8f046e9..b95ef9f 100644 (file)
@@ -339,7 +339,7 @@ private:
 
 public:
   ThreadKeyImpl(void (*destroy_fcn)(void*)) : destroy_hook(destroy_fcn) { key=TlsAlloc(); };
-  virtual ~ThreadKeyImpl() { destroy_hook(TlsGetValue(key)); TlsFree(key); }
+  virtual ~ThreadKeyImpl() { if (destroy_hook) destroy_hook(TlsGetValue(key)); TlsFree(key); }
 
   int setData(void* data) { TlsSetValue(key,data); return 0;}
   void* getData() { return TlsGetValue(key); }
index 81f517b..acb07b4 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 libeay32.lib saml_4.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 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"
 
 !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 libeay32.lib saml_4D.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 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"
 
 !ENDIF 
 
@@ -145,6 +145,10 @@ SOURCE=.\ShibPOSTProfileFactory.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\ShibSOAPBinding.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\SimpleAttribute.cpp
 # End Source File
 # Begin Source File
@@ -153,6 +157,10 @@ SOURCE=.\XML.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\XMLCredentials.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\XMLMetadata.cpp
 # End Source File
 # Begin Source File
index 27b7840..a71791b 100644 (file)
@@ -60,7 +60,7 @@
 #define __shib_h__
 
 #include <saml/saml.h>
-#include <openssl/x509.h>
+#include <openssl/ssl.h>
 
 #ifdef WIN32
 # ifndef SHIB_EXPORTS
 
 namespace shibboleth
 {
-#ifdef NO_RTTI
-  extern SHIB_EXPORTS const unsigned short RTTI_UnsupportedProtocolException;
-  extern SHIB_EXPORTS const unsigned short RTTI_OriginSiteMapperException;
-#endif
-
     #define DECLARE_SHIB_EXCEPTION(name,base) \
         class SHIB_EXPORTS name : public saml::base \
         { \
@@ -150,9 +145,18 @@ namespace shibboleth
         virtual saml::Iterator<XSECCryptoX509*> getCertificates(const XMLCh* subject) const=0;
         virtual bool validate(const ISite* site, saml::Iterator<XSECCryptoX509*> certs) const=0;
         virtual bool validate(const ISite* site, saml::Iterator<const XMLCh*> certs) const=0;
+        virtual bool attach(const ISite* site, SSL_CTX* ctx) const=0;
         virtual ~ITrust() {}
     };
     
+    struct SHIB_EXPORTS ICredentials
+    {
+        virtual void lock()=0;
+        virtual void unlock()=0;
+        virtual bool attach(const XMLCh* subject, const ISite* relyingParty, SSL_CTX* ctx) const=0;
+        virtual ~ICredentials() {}
+    };
+    
     struct SHIB_EXPORTS IAttributeRule
     {
         virtual const XMLCh* getName() const=0;
@@ -175,12 +179,6 @@ namespace shibboleth
     };
 
 #ifdef SHIB_INSTANTIATE
-# ifdef NO_RTTI
-    const unsigned short RTTI_UnsupportedProtocolException=     RTTI_EXTENSION_BASE;
-    const unsigned short RTTI_MetadataException=                RTTI_EXTENSION_BASE+1;
-# endif
-//    template class SHIB_EXPORTS saml::Iterator<std::pair<saml::xstring,bool> >;
-//    template class SHIB_EXPORTS saml::ArrayIterator<std::pair<saml::xstring,bool> >;
     template class SHIB_EXPORTS saml::Iterator<const IContactInfo*>;
     template class SHIB_EXPORTS saml::ArrayIterator<const IContactInfo*>;
     template class SHIB_EXPORTS saml::Iterator<const IAuthority*>;
@@ -191,6 +189,8 @@ namespace shibboleth
     template class SHIB_EXPORTS saml::ArrayIterator<IMetadata*>;
     template class SHIB_EXPORTS saml::Iterator<ITrust*>;
     template class SHIB_EXPORTS saml::ArrayIterator<ITrust*>;
+    template class SHIB_EXPORTS saml::Iterator<ICredentials*>;
+    template class SHIB_EXPORTS saml::ArrayIterator<ICredentials*>;
     template class SHIB_EXPORTS saml::Iterator<IAAP*>;
     template class SHIB_EXPORTS saml::ArrayIterator<IAAP*>;
 #endif
@@ -277,35 +277,6 @@ namespace shibboleth
         ShibPOSTProfile& operator=(const ShibPOSTProfile&) {return *this;}
     };
 
-    class SHIB_EXPORTS ClubShibPOSTProfile : public ShibPOSTProfile
-    {
-    public:
-        ClubShibPOSTProfile(const saml::Iterator<const XMLCh*>& policies, const XMLCh* receiver, int ttlSeconds);
-        ClubShibPOSTProfile(const saml::Iterator<const XMLCh*>& policies, const XMLCh* issuer);
-        virtual ~ClubShibPOSTProfile();
-
-        virtual saml::SAMLResponse* prepare(
-            const XMLCh* recipient,
-            const XMLCh* name,
-            const XMLCh* nameQualifier,
-            const XMLCh* subjectIP,
-            const XMLCh* authMethod,
-            time_t authInstant,
-            const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings,
-            XSECCryptoKey* responseKey,
-            const saml::Iterator<XSECCryptoX509*>& responseCerts=EMPTY(XSECCryptoX509*),
-            XSECCryptoKey* assertionKey=NULL,
-            const saml::Iterator<XSECCryptoX509*>& assertionCerts=EMPTY(XSECCryptoX509*)
-            );
-
-    protected:
-        virtual void verifySignature(
-            const saml::SAMLSignedObject& obj,
-            const IOriginSite* originSite,
-            const XMLCh* signerName,
-            XSECCryptoKey* knownKey=NULL);
-    };
-
     class SHIB_EXPORTS ShibPOSTProfileFactory
     {
     public:
@@ -339,12 +310,19 @@ namespace shibboleth
         saml::Iterator<XSECCryptoX509*> getCertificates(const XMLCh* subject);
         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:
         Trust(const Trust&);
         void operator=(const Trust&);
         ITrust* m_mapper;
     };
+    
+    class SHIB_EXPORTS Credentials
+    {
+    public:
+        static bool attach(const XMLCh* subject, const ISite* relyingParty, SSL_CTX* ctx);
+    };
 
     class SHIB_EXPORTS AAP
     {
@@ -365,6 +343,7 @@ namespace shibboleth
 
     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); }
     
     class SHIB_EXPORTS ShibConfig
@@ -383,6 +362,7 @@ namespace shibboleth
         // allows pluggable implementations of metadata
         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, AAPFactory* factory)=0;
         virtual void regFactory(const char* type, saml::SAMLAttributeFactory* factory)=0;
         virtual void unregFactory(const char* type)=0;
@@ -392,6 +372,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 saml::Iterator<IAAP*> getAAPProviders() const=0;
         virtual saml::SAMLAttributeFactory* getAttributeFactory(const char* type) const=0;
     };
@@ -400,6 +381,12 @@ namespace shibboleth
     {
         static const XMLCh SHIB_ATTRIBUTE_NAMESPACE_URI[];
         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; 
     };
 
@@ -429,8 +416,17 @@ namespace shibboleth
             static const XMLCh OriginSite[];
             static const XMLCh SiteGroup[];
             
+            static const XMLCh Credentials[];
+            static const XMLCh Exponent[];
             static const XMLCh KeyAuthority[];
+            static const XMLCh KeyUse[];
+            static const XMLCh Modulus[];
+            static const XMLCh RelyingParty[];
+            static const XMLCh RetrievalMethod[];
+            static const XMLCh RSAKeyValue[];
             static const XMLCh Trust[];
+            static const XMLCh URI[];
+            static const XMLCh VerifyDepth[];
 
             static const XMLCh Accept[];
             static const XMLCh Alias[];
@@ -459,20 +455,14 @@ namespace shibboleth
         };
     };
 
-
     class SHIB_EXPORTS SAMLBindingFactory
     {
     public:
-        static saml::SAMLBinding* getInstance(const XMLCh* protocol=saml::SAMLBinding::SAML_SOAP_HTTPS);
+        static saml::SAMLBinding* getInstance(
+            const XMLCh* subject,
+            const ISite* relyingParty,
+            const XMLCh* protocol=saml::SAMLBinding::SAML_SOAP_HTTPS);
     };
-
-    // OpenSSL Utilities
-
-    // Log errors from OpenSSL error queue.
-    void log_openssl();
-
-    // build an OpenSSL cert out of a base-64 encoded DER buffer (XML style)
-    X509* B64_to_X509(const char* buf);
 }
 
 #endif