--- /dev/null
+/*
+ * 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.
+ */
+
+/* siterefresh.cpp - command-line tool to refresh and verify site metadata
+
+ Scott Cantor
+ 5/12/03
+
+ $History:$
+*/
+
+#include "../shib/shib.h"
+
+#include <fstream>
+#include <log4cpp/Category.hh>
+#include <xercesc/framework/URLInputSource.hpp>
+#include <xsec/enc/XSECCryptoProvider.hpp>
+#include <xsec/enc/XSECKeyInfoResolverDefault.hpp>
+#include <xsec/enc/XSECCryptoException.hpp>
+#include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
+#include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
+#include <xsec/framework/XSECProvider.hpp>
+#include <xsec/framework/XSECException.hpp>
+#include <xsec/dsig/DSIGTransformC14n.hpp>
+#include <xsec/dsig/DSIGReference.hpp>
+#include <xsec/dsig/DSIGTransformList.hpp>
+
+#ifdef WIN32
+# define DEFAULT_SCHEMA_DIR "/shibboleth/etc/shibboleth/"
+#else
+# define DEFAULT_SCHEMA_DIR "/opt/shibboleth/etc/shibboleth/"
+#endif
+
+using namespace std;
+using namespace saml;
+using namespace shibboleth;
+using namespace log4cpp;
+
+void verifySignature(DOMDocument* doc, DOMElement* sigNode, const char* cert)
+{
+ Category& log=Category::getInstance("siterefresh");
+
+ // Load the certificate, stripping the first and last lines.
+ string certbuf,line1,line2;
+ auto_ptr<OpenSSLCryptoX509> x509(new OpenSSLCryptoX509());
+ ifstream infile(cert);
+ getline(infile,line1);
+ while (!getline(infile,line1).fail())
+ {
+ certbuf+=line2;
+ line2=line1;
+ }
+ x509->loadX509Base64Bin(certbuf.data(),certbuf.length());
+
+ // Load the signature.
+ XSECProvider prov;
+ DSIGSignature* sig=NULL;
+ try
+ {
+ sig=prov.newSignatureFromDOM(doc,sigNode);
+ sig->load();
+
+ bool valid=false;
+
+ // Verify the signature coverage.
+ DSIGReferenceList* refs=sig->getReferenceList();
+ if (sig->getSignatureMethod()==SIGNATURE_RSA && refs && refs->getSize()==1)
+ {
+ DSIGReference* ref=refs->item(0);
+ if (ref)
+ {
+ const XMLCh* URI=ref->getURI();
+ if (URI==NULL || *URI==0)
+ {
+ DSIGTransformList* tlist=ref->getTransforms();
+ for (int i=0; tlist && i<tlist->getSize(); i++)
+ {
+ if (tlist->item(i)->getTransformType()==TRANSFORM_ENVELOPED_SIGNATURE)
+ valid=true;
+ else if (tlist->item(i)->getTransformType()!=TRANSFORM_EXC_C14N)
+ {
+ valid=false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!valid)
+ {
+ log.error("detected an invalid signature profile");
+ throw InvalidCryptoException("detected an invalid signature profile");
+ }
+
+ sig->setSigningKey(x509->clonePublicKey());
+ if (!sig->verify())
+ {
+ log.error("detected an invalid signature value");
+ throw InvalidCryptoException("detected an invalid signature value");
+ }
+
+ prov.releaseSignature(sig);
+ }
+ catch(...)
+ {
+ if (sig)
+ prov.releaseSignature(sig);
+ throw;
+ }
+}
+
+int main(int argc,char* argv[])
+{
+ int ret=0;
+ SAMLConfig& conf=SAMLConfig::getConfig();
+ char* url_param=NULL;
+ char* cert_param=NULL;
+ char* out_param=NULL;
+ char* path=DEFAULT_SCHEMA_DIR;
+
+ for (int i=1; i<argc; i++)
+ {
+ if (!strcmp(argv[i],"--schema") && i+1<argc)
+ path=argv[++i];
+ else if (!strcmp(argv[i],"--url") && i+1<argc)
+ url_param=argv[++i];
+ else if (!strcmp(argv[i],"--cert") && i+1<argc)
+ cert_param=argv[++i];
+ else if (!strcmp(argv[i],"--out") && i+1<argc)
+ out_param=argv[++i];
+ }
+
+ if (!url_param || !out_param)
+ {
+ cout << "usage: " << argv[0] << " --url <URL of metadata> --out <pathname to copy data into> [--cert <PEM Certificate> --schema <schema path>]" << endl;
+ exit(0);
+ }
+
+ Category::setRootPriority(ERROR);
+ conf.schema_dir=path;
+ if (!conf.init())
+ return -10;
+
+ Category& log=Category::getInstance("siterefresh");
+ saml::XML::registerSchema(shibboleth::XML::SHIB_NS,shibboleth::XML::SHIB_SCHEMA_ID);
+
+ try
+ {
+ // Parse the specified document.
+ saml::XML::Parser p;
+ static XMLCh base[]={chLatin_f, chLatin_i, chLatin_l, chLatin_e, chColon, chForwardSlash, chForwardSlash, chForwardSlash, chNull};
+ URLInputSource src(base,url_param);
+ Wrapper4InputSource dsrc(&src,false);
+ DOMDocument* doc=p.parse(dsrc);
+
+ // Examine the root element to be sure we know what we have.
+ DOMElement* e=doc->getDocumentElement();
+ if (XMLString::compareString(shibboleth::XML::SHIB_NS,e->getNamespaceURI()) ||
+ XMLString::compareString(shibboleth::XML::Literals::Sites,e->getLocalName()))
+ {
+ doc->release();
+ log.error("requires a valid site file: (shib:Sites as root element)");
+ throw OriginSiteMapperException("Construction requires a valid site file: (shib:Sites as root element)");
+ }
+
+ // If we're verifying, grab the embedded signature.
+ if (cert_param)
+ {
+ DOMNode* n=e->getLastChild();
+ while (n && n->getNodeType()!=DOMNode::ELEMENT_NODE)
+ n=n->getPreviousSibling();
+ if (n && !XMLString::compareString(saml::XML::XMLSIG_NS,n->getNamespaceURI()) &&
+ !XMLString::compareString(L(Signature),n->getLocalName()))
+ {
+ verifySignature(doc,static_cast<DOMElement*>(n),cert_param);
+ }
+ else
+ {
+ doc->release();
+ log.error("unable to locate a signature to verify in document");
+ throw OriginSiteMapperException("Verification implies that the document must be signed");
+ }
+ }
+
+ // Output the data to the specified file.
+ ofstream outfile(out_param);
+ outfile << *e;
+
+ doc->release();
+ }
+ catch (OriginSiteMapperException&)
+ {
+ ret=-1;
+ }
+ catch(SAMLException& e)
+ {
+ log.errorStream() << "caught a SAML exception: " << e << CategoryStream::ENDLINE;
+ ret=-2;
+ }
+ catch(XMLException& e)
+ {
+ auto_ptr<char> temp(XMLString::transcode(e.getMessage()));
+ log.errorStream() << "caught an XML exception: " << temp.get() << CategoryStream::ENDLINE;
+ ret=-3;
+ }
+ catch(XSECException& e)
+ {
+ auto_ptr<char> temp(XMLString::transcode(e.getMsg()));
+ log.errorStream() << "caught an XMLSec exception: " << temp.get() << CategoryStream::ENDLINE;
+ }
+ catch(XSECCryptoException& e)
+ {
+ log.errorStream() << "caught an XMLSecCrypto exception: " << e.getMsg() << CategoryStream::ENDLINE;
+ }
+ catch(...)
+ {
+ log.errorStream() << "caught an unknown exception" << CategoryStream::ENDLINE;
+ ret=-4;
+ }
+
+ conf.term();
+ return ret;
+}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="siterefresh" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=siterefresh - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "siterefresh.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "siterefresh.mak" CFG="siterefresh - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "siterefresh - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "siterefresh - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "siterefresh - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\opensaml\c" /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# 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 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 /subsystem:console /machine:I386
+# ADD LINK32 xerces-c_2.lib saml.lib xsec_lib_02.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\opensaml\c\saml\Release"
+
+!ELSEIF "$(CFG)" == "siterefresh - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "..\..\..\opensaml\c" /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# 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 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 /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 xerces-c_2D.lib saml.lib xsec_lib_02D.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\opensaml\c\saml\Debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "siterefresh - Win32 Release"
+# Name "siterefresh - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\siterefresh.cpp
+# End Source File
+# End Target
+# End Project