Convert logging to log4shib via compile time switch.
[shibboleth/opensaml2.git] / saml / binding / impl / ArtifactMap.cpp
index 0b61a7f..19c92a1 100644 (file)
 #include "binding/ArtifactMap.h"
 #include "binding/SAMLArtifact.h"
 
-#include <log4cpp/Category.hh>
 #include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/logging.h>
 #include <xmltooling/XMLObjectBuilder.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace opensaml;
+using namespace xmltooling::logging;
 using namespace xmltooling;
-using namespace log4cpp;
 using namespace std;
 
 namespace opensaml {
@@ -49,6 +49,7 @@ namespace opensaml {
         }
         void storeContent(XMLObject* content, const SAMLArtifact* artifact, const char* relyingParty, int TTL);
         XMLObject* retrieveContent(const SAMLArtifact* artifact, const char* relyingParty);
+        string getRelyingParty(const SAMLArtifact* artifact);
     
     private:
         struct SAML_DLLLOCAL Mapping {
@@ -64,6 +65,11 @@ namespace opensaml {
         map<string,Mapping> m_artMap;
         multimap<time_t,string> m_expMap;
     };
+
+    static const XMLCh artifactTTL[] =  UNICODE_LITERAL_11(a,r,t,i,f,a,c,t,T,T,L);
+    static const XMLCh context[] =      UNICODE_LITERAL_7(c,o,n,t,e,x,t);
+    static const XMLCh Mapping[] =      UNICODE_LITERAL_7(M,a,p,p,i,n,g);
+    static const XMLCh _relyingParty[] = UNICODE_LITERAL_12(r,e,l,y,i,n,g,P,a,r,t,y);
 };
 
 void ArtifactMappings::removeMapping(const map<string,Mapping>::iterator& i)
@@ -100,7 +106,7 @@ void ArtifactMappings::storeContent(XMLObject* content, const SAMLArtifact* arti
     if (relyingParty)
         m.m_relying = relyingParty;
     m.m_expires = now + TTL;
-    m_expMap.insert(make_pair(m.m_expires,hexed));
+    m_expMap.insert(pair<const time_t,string>(m.m_expires,hexed));
 }
 
 XMLObject* ArtifactMappings::retrieveContent(const SAMLArtifact* artifact, const char* relyingParty)
@@ -135,21 +141,48 @@ XMLObject* ArtifactMappings::retrieveContent(const SAMLArtifact* artifact, const
     return ret;
 }
 
-ArtifactMap::ArtifactMap(xmltooling::StorageService* storage, const char* context, int artifactTTL)
-    : m_storage(storage), m_context(context ? context : "opensaml::ArtifactMap"), m_mappings(NULL), m_artifactTTL(artifactTTL)
+string ArtifactMappings::getRelyingParty(const SAMLArtifact* artifact)
+{
+    map<string,Mapping>::iterator i=m_artMap.find(SAMLArtifact::toHex(artifact->getMessageHandle()));
+    if (i==m_artMap.end())
+        throw BindingException("Requested artifact not in map or may have expired.");
+    return i->second.m_relying;
+}
+
+ArtifactMap::ArtifactMap(xmltooling::StorageService* storage, const char* context, unsigned int artifactTTL)
+    : m_storage(storage), m_context((context && *context) ? context : "opensaml::ArtifactMap"), m_mappings(NULL), m_artifactTTL(artifactTTL)
 {
     if (!m_storage)
         m_mappings = new ArtifactMappings();
 }
 
+ArtifactMap::ArtifactMap(const DOMElement* e, xmltooling::StorageService* storage)
+    : m_storage(storage), m_mappings(NULL), m_artifactTTL(180)
+{
+    if (e) {
+        auto_ptr_char c(e->getAttributeNS(NULL, context));
+        if (c.get() && *c.get())
+            m_context = c.get();
+        else
+            m_context = "opensaml::ArtifactMap";
+        
+        const XMLCh* TTL = e->getAttributeNS(NULL, artifactTTL);
+        if (TTL) {
+            m_artifactTTL = XMLString::parseInt(TTL);
+            if (!m_artifactTTL)
+                m_artifactTTL = 180;
+        }
+    }
+    
+    if (!m_storage)
+        m_mappings = new ArtifactMappings();
+}
+
 ArtifactMap::~ArtifactMap()
 {
     delete m_mappings;
 }
 
-static const XMLCh M[] = UNICODE_LITERAL_7(M,a,p,p,i,n,g);
-static const XMLCh RP[] = UNICODE_LITERAL_12(r,e,l,y,i,n,g,P,a,r,t,y);
-
 void ArtifactMap::storeContent(XMLObject* content, const SAMLArtifact* artifact, const char* relyingParty)
 {
     if (content->getParent())
@@ -163,17 +196,22 @@ void ArtifactMap::storeContent(XMLObject* content, const SAMLArtifact* artifact,
     // Build a DOM with the same document to store the relyingParty mapping.
     if (relyingParty) {
         auto_ptr_XMLCh temp(relyingParty);
-        root = root->getOwnerDocument()->createElementNS(NULL,M);
-        root->setAttributeNS(NULL,RP,temp.get());
+        root = root->getOwnerDocument()->createElementNS(NULL,Mapping);
+        root->setAttributeNS(NULL,_relyingParty,temp.get());
         root->appendChild(content->getDOM());
     }
     
     // Serialize the root element, whatever it is, for storage.
     string xmlbuf;
     XMLHelper::serialize(root, xmlbuf);
-    m_storage->createText(
-        m_context.c_str(), SAMLArtifact::toHex(artifact->getMessageHandle()).c_str(), xmlbuf.c_str(), time(NULL) + m_artifactTTL
-        );
+    if (!m_storage->createText(
+        m_context.c_str(),
+        SAMLArtifact::toHex(artifact->getMessageHandle()).c_str(),
+        xmlbuf.c_str(),
+        time(NULL) + m_artifactTTL
+        )) {
+        throw IOException("Attempt to insert duplicate artifact into map.");
+    }
         
     // Cleanup by destroying XML.
     delete content;
@@ -184,26 +222,27 @@ XMLObject* ArtifactMap::retrieveContent(const SAMLArtifact* artifact, const char
 #ifdef _DEBUG
     xmltooling::NDC ndc("retrieveContent");
 #endif
+    Category& log=Category::getInstance(SAML_LOGCAT".ArtifactMap");
 
     if (!m_storage)
         return m_mappings->retrieveContent(artifact, relyingParty);
     
+    // Read the mapping and then delete it.
     string xmlbuf;
     string key = SAMLArtifact::toHex(artifact->getMessageHandle());
     if (!m_storage->readText(m_context.c_str(), key.c_str(), &xmlbuf))
         throw BindingException("Artifact not found in mapping database.");
+    m_storage->deleteText(m_context.c_str(), key.c_str());
     
+    // Parse the data back into XML.
     istringstream is(xmlbuf);
     DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(is);
     XercesJanitor<DOMDocument> janitor(doc);
-
-    Category& log=Category::getInstance(SAML_LOGCAT".ArtifactMap");
-    m_storage->deleteText(m_context.c_str(), key.c_str());
     
     // Check the root element.
     DOMElement* messageRoot = doc->getDocumentElement();
-    if (XMLHelper::isNodeNamed(messageRoot, NULL, M)) {
-        auto_ptr_char temp(messageRoot->getAttributeNS(NULL,RP));
+    if (XMLHelper::isNodeNamed(messageRoot, NULL, Mapping)) {
+        auto_ptr_char temp(messageRoot->getAttributeNS(NULL,_relyingParty));
         if (!relyingParty || strcmp(temp.get(),relyingParty)) {
             log.warn("request from (%s) for artifact issued to (%s)", relyingParty ? relyingParty : "unknown", temp.get());
             throw BindingException("Unauthorized artifact mapping request.");
@@ -218,3 +257,26 @@ XMLObject* ArtifactMap::retrieveContent(const SAMLArtifact* artifact, const char
     log.debug("resolved artifact for (%s)", relyingParty ? relyingParty : "unknown");
     return xmlObject;
 }
+
+string ArtifactMap::getRelyingParty(const SAMLArtifact* artifact)
+{
+    if (!m_storage)
+        return m_mappings->getRelyingParty(artifact);
+    
+    string xmlbuf;
+    if (!m_storage->readText(m_context.c_str(), SAMLArtifact::toHex(artifact->getMessageHandle()).c_str(), &xmlbuf))
+        throw BindingException("Artifact not found in mapping database.");
+    
+    // Parse the data back into XML.
+    istringstream is(xmlbuf);
+    DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(is);
+    XercesJanitor<DOMDocument> janitor(doc);
+    
+    // Check the root element.
+    DOMElement* messageRoot = doc->getDocumentElement();
+    if (XMLHelper::isNodeNamed(messageRoot, NULL, Mapping)) {
+        auto_ptr_char temp(messageRoot->getAttributeNS(NULL,_relyingParty));
+        return temp.get();
+    }
+    return string();
+}