From: cantor Date: Fri, 4 May 2007 17:44:38 +0000 (+0000) Subject: Delete old files. X-Git-Tag: 2.4~951 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fsp.git;a=commitdiff_plain;h=8d2204c44dfcd6e91e436a38fe6ff11e8562c477 Delete old files. git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2231 cb58f699-b61c-0410-a6fe-9272a202ed29 --- diff --git a/Makefile.am b/Makefile.am index d7ffc94..be61416 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,8 +5,7 @@ ACLOCAL_AMFLAGS = -I . EXTRA_DIST = \ schemas doc isapi_shib isapi_shib_gui \ Shibboleth.sln libtool.m4 acx_pthread.m4 acx_rpctest.m4 depcomp \ - config_win32.h shibtest/shibtest.vcproj \ - shibboleth.spec.in shibboleth.spec pkginfo.in pkginfo checkinstall + config_win32.h shibboleth.spec.in shibboleth.spec pkginfo.in pkginfo checkinstall dist-hook: rm -rf `find $(distdir)/schemas -name Makefile` diff --git a/doc/CURL.LICENSE b/doc/CURL.LICENSE deleted file mode 100644 index d7ad261..0000000 --- a/doc/CURL.LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1996 - 2004, Daniel Stenberg, . - -All rights reserved. - -Permission to use, copy, modify, and distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright -notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall not -be used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization of the copyright holder. diff --git a/doc/Makefile.am b/doc/Makefile.am index e3f76c3..a1428af 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -11,7 +11,6 @@ pkgdoc_DATA = \ README.txt \ OPENSSL.LICENSE \ LOG4CPP.LICENSE \ - CURL.LICENSE \ mysql-4.0.12.diff \ main.css \ logo.jpg \ No newline at end of file diff --git a/shib-target/ArtifactMapper.cpp b/shib-target/ArtifactMapper.cpp deleted file mode 100644 index 81acf21..0000000 --- a/shib-target/ArtifactMapper.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* ArtifactMapper.cpp - a ShibTarget-aware SAML artifact->binding mapper - - Scott Cantor - 2/20/05 - - $History:$ -*/ - -#include "internal.h" -#include -#include - -using namespace shibsp; -using namespace shibtarget; -using namespace saml; -using namespace opensaml::saml2md; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; -using xmlsignature::CredentialResolver; - -SAMLResponse* STArtifactMapper::resolve(SAMLRequest* request) -{ - Category& log=Category::getInstance("shibtarget.ArtifactMapper"); - - // First do a search for the issuer. - SAMLArtifact* artifact=request->getArtifacts().next(); - auto_ptr os2art(opensaml::SAMLArtifact::parse(artifact->encode().c_str())); - - MetadataProvider* m=m_app->getMetadataProvider(); - const EntityDescriptor* entity=m->getEntityDescriptor(os2art.get()); - if (!entity) { - log.error( - "metadata lookup failed, unable to determine issuer of artifact (0x%s)", - opensaml::SAMLArtifact::toHex(artifact->getBytes()).c_str() - ); - throw MetadataException("Metadata lookup failed, unable to determine artifact issuer"); - } - - xmltooling::auto_ptr_char issuer(entity->getEntityID()); - log.info("lookup succeeded, artifact issued by (%s)", issuer.get()); - - // Sign it? - const PropertySet* credUse=m_app->getCredentialUse(entity); - pair signRequest=credUse ? credUse->getBool("signRequest") : make_pair(false,false); - pair signatureAlg=credUse ? credUse->getString("signatureAlg") : pair(false,NULL); - if (!signatureAlg.first) - signatureAlg.second=URI_ID_RSA_SHA1; - pair digestAlg=credUse ? credUse->getString("digestAlg") : pair(false,NULL); - if (!digestAlg.first) - digestAlg.second=URI_ID_SHA1; - pair signedResponse=credUse ? credUse->getBool("signedResponse") : make_pair(false,false); - pair signingCred=credUse ? credUse->getString("Signing") : pair(false,NULL); - if (signRequest.first && signRequest.second && signingCred.first) { - if (request->getMinorVersion()==1) { - CredentialResolver* cr=SPConfig::getConfig().getServiceProvider()->getCredentialResolver(signingCred.second); - if (cr) { - xmltooling::Locker locker(cr); - request->sign(cr->getKey(),cr->getCertificates(),signatureAlg.second,digestAlg.second); - } - else - log.error("unable to sign artifact request, specified credential (%s) was not found",signingCred.second); - } - else - log.error("unable to sign SAML 1.0 artifact request, only SAML 1.1 defines signing adequately"); - } - - SAMLResponse* response = NULL; - bool authenticated = false; - static const XMLCh https[] = {chLatin_h, chLatin_t, chLatin_t, chLatin_p, chLatin_s, chColon, chNull}; - - // Depends on type of artifact. - const SAMLArtifactType0001* type1=dynamic_cast(artifact); - if (type1) { - // With type 01, any endpoint will do. - const IDPSSODescriptor* idp=entity->getIDPSSODescriptor( - request->getMinorVersion()==1 ? samlconstants::SAML11_PROTOCOL_ENUM : samlconstants::SAML10_PROTOCOL_ENUM - ); - if (idp) { - ShibHTTPHook::ShibHTTPHookCallContext callCtx(credUse,idp); - const vector& endpoints=idp->getArtifactResolutionServices(); - for (vector::const_iterator ep=endpoints.begin(); !response && ep!=endpoints.end(); ++ep) { - const SAMLBinding* binding = m_app->getBinding((*ep)->getBinding()); - if (!binding) { - xmltooling::auto_ptr_char prot((*ep)->getBinding()); - log.warn("skipping binding on unsupported protocol (%s)", prot.get()); - continue; - } - try { - response = binding->send((*ep)->getLocation(),*request,&callCtx); - if (log.isDebugEnabled()) - log.debugStream() << "SAML response from artifact request:\n" << *response << CategoryStream::ENDLINE; - - if (!response->getAssertions().hasNext()) { - delete response; - throw FatalProfileException("No SAML assertions returned in response to artifact profile request."); - } - authenticated = callCtx.isAuthenticated() && !XMLString::compareNString((*ep)->getLocation(),https,6); - } - catch (XMLToolingException& ex) { - annotateException(&ex,idp); // rethrows it - } - catch (exception& ex) { - opensaml::BindingException ex2(ex.what()); - annotateException(&ex2,idp); // rethrows it - } - } - } - } - else { - const SAMLArtifactType0002* type2=dynamic_cast(artifact); - if (type2) { - // With type 02, we have to find the matching location. - const IDPSSODescriptor* idp=entity->getIDPSSODescriptor( - request->getMinorVersion()==1 ? samlconstants::SAML11_PROTOCOL_ENUM : samlconstants::SAML10_PROTOCOL_ENUM - ); - if (idp) { - ShibHTTPHook::ShibHTTPHookCallContext callCtx(credUse,idp); - const vector& endpoints=idp->getArtifactResolutionServices(); - for (vector::const_iterator ep=endpoints.begin(); !response && ep!=endpoints.end(); ++ep) { - xmltooling::auto_ptr_char loc((*ep)->getLocation()); - if (strcmp(loc.get(),type2->getSourceLocation())) - continue; - const SAMLBinding* binding = m_app->getBinding((*ep)->getBinding()); - if (!binding) { - xmltooling::auto_ptr_char prot((*ep)->getBinding()); - log.warn("skipping binding on unsupported protocol (%s)", prot.get()); - continue; - } - try { - response = binding->send((*ep)->getLocation(),*request,&callCtx); - if (log.isDebugEnabled()) - log.debugStream() << "SAML response from artifact request:\n" << *response << CategoryStream::ENDLINE; - - if (!response->getAssertions().hasNext()) { - delete response; - throw FatalProfileException("No SAML assertions returned in response to artifact profile request."); - } - authenticated = callCtx.isAuthenticated() && !XMLString::compareNString((*ep)->getLocation(),https,6); - } - catch (XMLToolingException& ex) { - annotateException(&ex,idp); // rethrows it - } - catch (exception& ex) { - opensaml::BindingException ex2(ex.what()); - annotateException(&ex2,idp); // rethrows it - } - } - } - } - else { - log.error("unrecognized artifact type (0x%s)", SAMLArtifact::toHex(artifact->getTypeCode()).c_str()); - throw xmltooling::UnknownExtensionException( - string("Received unrecognized artifact type (0x") + SAMLArtifact::toHex(artifact->getTypeCode()) + ")" - ); - } - } - - if (!response) { - log.error("unable to locate acceptable binding/endpoint to resolve artifact"); - MetadataException ex("Unable to locate acceptable binding/endpoint to resolve artifact."); - annotateException(&ex,entity); // throws it - } - else if (!response->isSigned()) { - if (!authenticated || (signedResponse.first && signedResponse.second)) { - log.error("unsigned response obtained, but it must be signed."); - XMLSecurityException ex("Unable to obtain a signed response from artifact request."); - annotateException(&ex,entity); // throws it - } - } - - return response; -} diff --git a/shib-target/Makefile.am b/shib-target/Makefile.am deleted file mode 100644 index 2ffa8d7..0000000 --- a/shib-target/Makefile.am +++ /dev/null @@ -1,40 +0,0 @@ -## $Id$ - -AUTOMAKE_OPTIONS = foreign - -pkgsysconfdir = $(sysconfdir)/@PACKAGE@ -pkgxmldir = $(datadir)/xml/@PACKAGE@ - -lib_LTLIBRARIES = libshib-target.la - -libshib_targetdir = $(includedir)/shib-target -libshib_target_HEADERS = shib-target.h shib-paths.h -noinst_HEADERS = internal.h - -libshib_target_la_SOURCES = \ - ArtifactMapper.cpp \ - ShibHTTPHook.cpp \ - shib-ccache.cpp \ - shib-config.cpp \ - shib-handlers.cpp \ - shib-ini.cpp - -# this is different from the project version -# http://sources.redhat.com/autobook/autobook/autobook_91.html -libshib_target_la_LDFLAGS = -version-info 7:0:0 - - - -shib-paths.h: ${srcdir}/shib-paths.h.in Makefile ${top_builddir}/config.status - rm -f $@.tmp - sed < ${srcdir}/$@.in > $@.tmp \ - -e 's:@-PKGSYSCONFDIR-@:${pkgsysconfdir}:' \ - -e 's:@-PKGXMLDIR-@:${pkgxmldir}:' - cmp -s $@ $@.tmp || mv $@.tmp $@ - rm -f $@.tmp - -install-exec-hook: - for la in $(lib_LTLIBRARIES) ; do rm -f $(DESTDIR)$(libdir)/$$la ; done - -EXTRA_DIST = shibtarget.vcproj shib-paths.h.in resource.h shib-target.rc -BUILT_SOURCES = shib-paths.h diff --git a/shib-target/ShibHTTPHook.cpp b/shib-target/ShibHTTPHook.cpp deleted file mode 100644 index 01da9c0..0000000 --- a/shib-target/ShibHTTPHook.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* ShibHTTPHook.cpp - Shibboleth hook for SAML Binding with SSL callback - - Scott Cantor - 2/13/05 - - $History:$ -*/ - -#include "internal.h" - -#include -#include -#include - -#include -#include -#include - -using namespace shibsp; -using namespace shibtarget; -using namespace shibboleth; -using namespace saml; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; -using xmlsignature::OpenSSLCredentialResolver; - -/* - * Our verifier callback is a front-end for invoking each trust plugin until - * success, or we run out of plugins. - */ -static int verify_callback(X509_STORE_CTX* x509_ctx, void* arg) -{ - Category::getInstance("OpenSSL").debug("invoking default X509 verify callback"); -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) - ShibHTTPHook::ShibHTTPHookCallContext* ctx = reinterpret_cast(arg); -#else - // Yes, this sucks. I'd use TLS, but there's no really obvious spot to put the thread key - // and global variables suck too. We can't access the X509_STORE_CTX depth directly because - // OpenSSL only copies it into the context if it's >=0, and the unsigned pointer may be - // negative in the SSL structure's int member. - SSL* ssl = reinterpret_cast(X509_STORE_CTX_get_ex_data(x509_ctx,SSL_get_ex_data_X509_STORE_CTX_idx())); - ShibHTTPHook::ShibHTTPHookCallContext* ctx = - reinterpret_cast(SSL_get_verify_depth(ssl)); -#endif - - const OpenSSLTrustEngine* t = dynamic_cast(ctx->getHook()->getTrustEngine()); - if (!t || !t->validate(x509_ctx->cert,x509_ctx->untrusted,*(ctx->getRoleDescriptor()),false)) { // bypass name check (handled for us) - x509_ctx->error=X509_V_ERR_APPLICATION_VERIFICATION; // generic error, check log for plugin specifics - return 0; - } - - // Signal success. Hopefully it doesn't matter what's actually in the structure now. - return 1; -} - -/* - * OpenSAML callback is invoked during SSL context setup, before the handshake. - * We use it to attach credentials and our own certificate verifier callback above. - */ -static bool ssl_ctx_callback(void* ssl_ctx, void* userptr) -{ -#ifdef _DEBUG - xmltooling::NDC("ssl_ctx_callback"); -#endif - Category& log=Category::getInstance(SHIBT_LOGCAT".ShibHTTPHook"); - - try { - log.debug("OpenSAML invoked SSL context callback"); - ShibHTTPHook::ShibHTTPHookCallContext* ctx = reinterpret_cast(userptr); - const PropertySet* credUse=ctx->getCredentialUse(); - pair TLS=credUse ? credUse->getString("TLS") : pair(false,NULL); - if (TLS.first) { - OpenSSLCredentialResolver* cr=dynamic_cast(SPConfig::getConfig().getServiceProvider()->getCredentialResolver(TLS.second)); - if (cr) { - xmltooling::Locker locker(cr); - cr->attach(reinterpret_cast(ssl_ctx)); - } - else - log.error("unable to attach credentials to request using (%s), leaving anonymous",TLS.second); - } - else - log.warn("no TLS credentials supplied, leaving anonymous"); - - SSL_CTX_set_verify(reinterpret_cast(ssl_ctx),SSL_VERIFY_PEER,NULL); -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) - // With 0.9.7, we can pass a callback argument directly. - SSL_CTX_set_cert_verify_callback(reinterpret_cast(ssl_ctx),verify_callback,userptr); -#else - // With 0.9.6, there's no argument, so we're going to use a really embarrassing hack and - // stuff the argument in the depth property where it will get copied to the context object - // that's handed to the callback. - SSL_CTX_set_cert_verify_callback( - reinterpret_cast(ssl_ctx), - reinterpret_cast(verify_callback), - NULL - ); - SSL_CTX_set_verify_depth(reinterpret_cast(ssl_ctx),reinterpret_cast(userptr)); - -#endif - } - catch (SAMLException& e) { - log.error(string("caught a SAML exception while attaching credentials to request: ") + e.what()); - return false; - } -#ifndef _DEBUG - catch (...) { - log.error("caught an unknown exception while attaching credentials to request"); - return false; - } -#endif - - return true; -} - -bool ShibHTTPHook::outgoing(HTTPClient* conn, void* globalCtx, void* callCtx) -{ - // Sanity check... - if (globalCtx != this) - return false; - - // Clear authn status. - reinterpret_cast(callCtx)->m_authenticated=false; - - // The callCtx is our nested context class. Copy in the parent pointer. - reinterpret_cast(callCtx)->m_hook=this; - - // The hook function is called before connecting to the HTTP server. This - // gives us a chance to attach our own SSL callback, and set a version header. - if (!conn->setSSLCallback(ssl_ctx_callback,callCtx)) - return false; - - if (!conn->setRequestHeader("Shibboleth", PACKAGE_VERSION)) - return false; - if (!conn->setRequestHeader("Xerces-C", XERCES_FULLVERSIONDOT)) - return false; - if (!conn->setRequestHeader("XML-Security-C", XSEC_VERSION)) - return false; - if (!conn->setRequestHeader("OpenSAML-C", OPENSAML_FULLVERSIONDOT)) - return false; - - // Check for HTTP authentication... - const PropertySet* credUse=reinterpret_cast(callCtx)->getCredentialUse(); - pair authType=credUse ? credUse->getString("authType") : pair(false,NULL); - if (authType.first) { -#ifdef _DEBUG - saml::NDC("outgoing"); -#endif - Category& log=Category::getInstance(SHIBT_LOGCAT".ShibHTTPHook"); - HTTPClient::auth_t type=HTTPClient::auth_none; - pair username=credUse->getString("authUsername"); - pair password=credUse->getString("authPassword"); - if (!username.first || !password.first) { - log.error("HTTP authType (%s) specified but authUsername or authPassword was missing", authType.second); - return false; - } - else if (!strcmp(authType.second,"basic")) - type = HTTPClient::auth_basic; - else if (!strcmp(authType.second,"digest")) - type = HTTPClient::auth_digest; - else if (!strcmp(authType.second,"ntlm")) - type = HTTPClient::auth_ntlm; - else if (!strcmp(authType.second,"gss")) - type = HTTPClient::auth_gss; - else { - log.error("Unknown authType (%s) specified in CredentialUse element", authType.second); - return false; - } - log.debug("configured for HTTP authentication (method=%s, username=%s)", authType.second, username.second); - return conn->setAuth(type,username.second,password.second); - } - - // The best we can do is assume authentication succeeds because when libcurl reuses - // SSL and HTTP connections, no callback is made. Since we always authenticate SSL connections, - // the caller should check that the protocol is https. - reinterpret_cast(callCtx)->setAuthenticated(); - return true; -} diff --git a/shib-target/hresult.h b/shib-target/hresult.h deleted file mode 100644 index 63dabd0..0000000 --- a/shib-target/hresult.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * hresult.h - Code definitions -= */ - -#ifndef __shibtargethresult_h__ -#define __shibtargethresult_h__ - -#include - -/* Codes from 0x9000 - 0x9FFF in FACILITY_ITF are reserved for the Shibboleth SP */ - -#define SHIBSP_E_FIRST MAKE_HRESULT(SEVERITY_ERROR,FACILITY_ITF,SAML_E_LAST + 0x0001) -#define SHIBSP_E_LAST MAKE_HRESULT(SEVERITY_ERROR,FACILITY_ITF,SAML_E_LAST + 0x1000) - -#define SHIBSP_S_FIRST MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_ITF,SAML_S_LAST + 0x0001) -#define SHIBSP_S_LAST MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_ITF,SAML_S_LAST + 0x1000 - -/* Specific code definitions */ - -#define SHIBSP_E_UNSPECIFIED (SHIBSP_E_FIRST + 0L) - -#define SESSION_E_ADDRESSMISMATCH (SHIBSP_E_FIRST + 1L) -#define SESSION_E_EXPIRED (SHIBSP_E_FIRST + 2L) - -#endif diff --git a/shib-target/internal.h b/shib-target/internal.h deleted file mode 100644 index e103108..0000000 --- a/shib-target/internal.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* internal.h - internally visible declarations - - Scott Cantor - 6/29/03 - - $History:$ -*/ - -#ifndef __shibtarget_internal_h__ -#define __shibtarget_internal_h__ - -#ifdef WIN32 -# define _CRT_SECURE_NO_DEPRECATE 1 -# define _CRT_NONSTDC_NO_DEPRECATE 1 -#endif - -#ifdef WIN32 -# define SHIBTARGET_EXPORTS __declspec(dllexport) -#endif - -// eventually we might be able to support autoconf via cygwin... -#if defined (_MSC_VER) || defined(__BORLANDC__) -# include "config_win32.h" -#else -# include "config.h" -#endif - -#include - -#include "shib-target.h" -#include "hresult.h" - -#include -#include -#include -#include -#include -#include - - -#define SHIBT_L(s) shibtarget::XML::Literals::s -#define SHIBT_L_QNAME(p,s) shibtarget::XML::Literals::p##_##s -#define SHIBT_LOGCAT "shibtarget" -#define SHIBTRAN_LOGCAT "Shibboleth-TRANSACTION" - -namespace shibtarget { - // ST-aware class that maps SAML artifacts to appropriate binding information - class STArtifactMapper : public virtual saml::SAMLBrowserProfile::ArtifactMapper - { - public: - STArtifactMapper(const IApplication* application) : m_app(application) {} - virtual ~STArtifactMapper() {} - saml::SAMLResponse* resolve(saml::SAMLRequest* request); - - private: - const IApplication* m_app; - }; - - class STConfig : public ShibTargetConfig - { - public: - STConfig() : m_tranLog(NULL), m_tranLogLock(NULL) {} - ~STConfig() {} - - bool init(const char* schemadir); - bool load(const char* config); - void shutdown(); - - log4cpp::Category& getTransactionLog() { m_tranLogLock->lock(); return *m_tranLog; } - void releaseTransactionLog() { m_tranLogLock->unlock();} - private: - log4cpp::FixedContextCategory* m_tranLog; - xmltooling::Mutex* m_tranLogLock; - }; - - // TODO: move this over to shibsp lib. - xmltooling::PluginManager::Factory XMLServiceProviderFactory; -} - -#endif diff --git a/shib-target/resource.h b/shib-target/resource.h deleted file mode 100644 index 4fbd2cf..0000000 --- a/shib-target/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by shib-target.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/shib-target/shib-ccache.cpp b/shib-target/shib-ccache.cpp deleted file mode 100644 index 6eb8037..0000000 --- a/shib-target/shib-ccache.cpp +++ /dev/null @@ -1,1615 +0,0 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shib-ccache.cpp -- in-memory session cache plugin - * - * $Id$ - */ - -#include "internal.h" - -#if HAVE_UNISTD_H -# include -#endif - -#include -#include -#include -#include -#include - -#ifdef HAVE_LIBDMALLOCXX -#include -#endif - -using namespace shibsp; -using namespace shibtarget; -using namespace saml; -using namespace opensaml::saml2md; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; -using xmlsignature::CredentialResolver; - -static const XMLCh cleanupInterval[] = -{ chLatin_c, chLatin_l, chLatin_e, chLatin_a, chLatin_n, chLatin_u, chLatin_p, - chLatin_I, chLatin_n, chLatin_t, chLatin_e, chLatin_r, chLatin_v, chLatin_a, chLatin_l, chNull -}; -static const XMLCh cacheTimeout[] = -{ chLatin_c, chLatin_a, chLatin_c, chLatin_h, chLatin_e, - chLatin_T, chLatin_i, chLatin_m, chLatin_e, chLatin_o, chLatin_u, chLatin_t, chNull -}; -static const XMLCh AAConnectTimeout[] = -{ chLatin_A, chLatin_A, chLatin_C, chLatin_o, chLatin_n, chLatin_n, chLatin_e, chLatin_c, chLatin_t, - chLatin_T, chLatin_i, chLatin_m, chLatin_e, chLatin_o, chLatin_u, chLatin_t, chNull -}; -static const XMLCh AATimeout[] = -{ chLatin_A, chLatin_A, chLatin_T, chLatin_i, chLatin_m, chLatin_e, chLatin_o, chLatin_u, chLatin_t, chNull }; - -static const XMLCh defaultLifetime[] = -{ chLatin_d, chLatin_e, chLatin_f, chLatin_a, chLatin_u, chLatin_l, chLatin_t, - chLatin_L, chLatin_i, chLatin_f, chLatin_e, chLatin_t, chLatin_i, chLatin_m, chLatin_e, chNull -}; -static const XMLCh retryInterval[] = -{ chLatin_r, chLatin_e, chLatin_t, chLatin_r, chLatin_y, - chLatin_I, chLatin_n, chLatin_t, chLatin_e, chLatin_r, chLatin_v, chLatin_a, chLatin_l, chNull -}; -static const XMLCh strictValidity[] = -{ chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_c, chLatin_t, - chLatin_V, chLatin_a, chLatin_l, chLatin_i, chLatin_d, chLatin_i, chLatin_t, chLatin_y, chNull -}; -static const XMLCh propagateErrors[] = -{ chLatin_p, chLatin_r, chLatin_o, chLatin_p, chLatin_a, chLatin_g, chLatin_a, chLatin_t, chLatin_e, - chLatin_E, chLatin_r, chLatin_r, chLatin_o, chLatin_r, chLatin_s, chNull -}; -static const XMLCh writeThrough[] = -{ chLatin_w, chLatin_r, chLatin_i, chLatin_t, chLatin_e, - chLatin_T, chLatin_h, chLatin_r, chLatin_o, chLatin_u, chLatin_g, chLatin_h, chNull -}; - - -/* - * Stubbed out, inproc version of an ISessionCacheEntry - */ -class StubCacheEntry : public virtual ISessionCacheEntry -{ -public: - StubCacheEntry(Category* log) : m_log(log), m_pSubject(NULL), m_pUnfiltered(NULL), m_pFiltered(NULL) {} - StubCacheEntry(DDF& obj, Category* log) - : m_log(log), m_obj(obj), m_pSubject(NULL), m_pUnfiltered(NULL), m_pFiltered(NULL) {} - ~StubCacheEntry() { m_obj.destroy(); delete m_pSubject; delete m_pUnfiltered; delete m_pFiltered; } - void lock() {} - void unlock() { delete this; } - const char* getClientAddress() const { return m_obj["client_address"].string(); } - const char* getProviderId() const { return m_obj["provider_id"].string(); } - const char* getAuthnContext() const { return m_obj["authn_context"].string(); } - pair getSubject(bool xml=true, bool obj=false) const; - pair getTokens(bool xml=true, bool obj=false) const; - pair getFilteredTokens(bool xml=true, bool obj=false) const; - -protected: - Category* m_log; - mutable DDF m_obj; - mutable SAMLSubject* m_pSubject; - mutable SAMLResponse* m_pUnfiltered; - mutable SAMLResponse* m_pFiltered; -}; - -pair StubCacheEntry::getSubject(bool xml, bool obj) const -{ - const char* raw=m_obj["subject"].string(); - pair ret=pair(NULL,NULL); - if (xml) - ret.first=raw; - if (obj) { - if (!m_pSubject) { - istringstream in(raw); - m_log->debugStream() << "decoding subject: " << (raw ? raw : "(none)") << CategoryStream::ENDLINE; - m_pSubject=raw ? new SAMLSubject(in) : NULL; - } - ret.second=m_pSubject; - } - return ret; -} - -pair StubCacheEntry::getTokens(bool xml, bool obj) const -{ - const char* unfiltered=m_obj["tokens.unfiltered"].string(); - pair ret = pair(NULL,NULL); - if (xml) - ret.first=unfiltered; - if (obj) { - if (!m_pUnfiltered) { - if (unfiltered) { - istringstream in(unfiltered); - m_log->debugStream() << "decoding unfiltered tokens: " << unfiltered << CategoryStream::ENDLINE; - m_pUnfiltered=new SAMLResponse(in,m_obj["minor_version"].integer()); - } - } - ret.second=m_pUnfiltered; - } - return ret; -} - -pair StubCacheEntry::getFilteredTokens(bool xml, bool obj) const -{ - const char* filtered=m_obj["tokens.filtered"].string(); - if (!filtered) - return getTokens(xml,obj); - pair ret = pair(NULL,NULL); - if (xml) - ret.first=filtered; - if (obj) { - if (!m_pFiltered) { - istringstream in(filtered); - m_log->debugStream() << "decoding filtered tokens: " << filtered << CategoryStream::ENDLINE; - m_pFiltered=new SAMLResponse(in,m_obj["minor_version"].integer()); - } - ret.second=m_pFiltered; - } - return ret; -} - -/* - * Remoting front-half of session cache, drops out in single process deployments. - * TODO: Add buffering of frequently-used entries. - */ -class StubCache : public virtual ISessionCache -{ -public: - StubCache(const DOMElement* e); - - string insert( - const IApplication* application, - const RoleDescriptor* role, - const char* client_addr, - const SAMLSubject* subject, - const char* authnContext, - const SAMLResponse* tokens - ); - ISessionCacheEntry* find(const char* key, const IApplication* application, const char* client_addr); - void remove(const char* key, const IApplication* application, const char* client_addr); - - bool setBackingStore(ISessionCacheStore*) { return false; } - -private: - Category* m_log; -}; - -StubCache::StubCache(const DOMElement* e) : m_log(&Category::getInstance(SHIBT_LOGCAT".SessionCache")) {} - -/* - * The public methods are remoted using the message passing system. - * In practice, insert is unlikely to be used remotely, but just in case... - */ - -string StubCache::insert( - const IApplication* application, - const RoleDescriptor* role, - const char* client_addr, - const SAMLSubject* subject, - const char* authnContext, - const SAMLResponse* tokens - ) -{ - DDF in("SessionCache::insert"),out; - DDFJanitor jin(in),jout(out); - in.structure(); - in.addmember("application_id").string(application->getId()); - in.addmember("client_address").string(client_addr); - xmltooling::auto_ptr_char provid(dynamic_cast(role->getParent())->getEntityID()); - in.addmember("provider_id").string(provid.get()); - in.addmember("major_version").integer(1); - in.addmember("minor_version").integer(tokens->getMinorVersion()); - in.addmember("authn_context").string(authnContext); - - ostringstream os; - os << *subject; - in.addmember("subject").string(os.str().c_str()); - os.str(""); - os << *tokens; - in.addmember("tokens.unfiltered").string(os.str().c_str()); - - out=SPConfig::getConfig().getServiceProvider()->getListenerService()->send(in); - if (out["key"].isstring()) - return out["key"].string(); - throw opensaml::RetryableProfileException("A remoted cache insertion operation did not return a usable session key."); -} - -ISessionCacheEntry* StubCache::find(const char* key, const IApplication* application, const char* client_addr) -{ - DDF in("SessionCache::find"),out; - DDFJanitor jin(in); - in.structure(); - in.addmember("key").string(key); - in.addmember("application_id").string(application->getId()); - in.addmember("client_address").string(client_addr); - - try { - out=SPConfig::getConfig().getServiceProvider()->getListenerService()->send(in); - if (!out.isstruct()) { - out.destroy(); - return NULL; - } - - // Wrap the results in a stub entry and return it to the caller. - return new StubCacheEntry(out,m_log); - } - catch (...) { - out.destroy(); - throw; - } -} - -void StubCache::remove(const char* key, const IApplication* application, const char* client_addr) -{ - DDF in("SessionCache::remove"); - DDFJanitor jin(in); - in.structure(); - in.addmember("key").string(key); - in.addmember("application_id").string(application->getId()); - in.addmember("client_address").string(client_addr); - - SPConfig::getConfig().getServiceProvider()->getListenerService()->send(in); -} - -/* - * Long-lived cache entries that store the actual sessions and - * wrap attribute query/refresh/filtering - */ -class MemorySessionCache; -class MemorySessionCacheEntry : public virtual ISessionCacheEntry, public virtual StubCacheEntry -{ -public: - MemorySessionCacheEntry( - MemorySessionCache* cache, - const char* key, - const IApplication* application, - const RoleDescriptor* role, - const char* client_addr, - const SAMLSubject* subject, - const char* authnContext, - const SAMLResponse* tokens - ); - MemorySessionCacheEntry( - MemorySessionCache* cache, - const char* key, - const IApplication* application, - const RoleDescriptor* role, - const char* client_addr, - const char* subject, - const char* authnContext, - const char* tokens, - int majorVersion, - int minorVersion, - time_t created, - time_t accessed - ); - ~MemorySessionCacheEntry(); - - void lock() { m_lock->lock(); } - void unlock() { m_lock->unlock(); } - - HRESULT isValid(const IApplication* application, const char* client_addr) const; - void populate(const IApplication* application, const EntityDescriptor* source, bool initial=false) const; - bool checkApplication(const IApplication* application) { return (m_obj["application_id"]==application->getId()); } - time_t created() const { return m_sessionCreated; } - time_t lastAccess() const { return m_lastAccess; } - const DDF& getDDF() const { return m_obj; } - -private: - bool hasAttributes(const SAMLResponse& r) const; - time_t calculateExpiration(const SAMLResponse& r) const; - pair getNewResponse(const IApplication* application, const EntityDescriptor* source) const; - SAMLResponse* filter(const SAMLResponse* r, const IApplication* application, const RoleDescriptor* role) const; - - time_t m_sessionCreated; - mutable time_t m_responseExpiration, m_lastAccess, m_lastRetry; - - MemorySessionCache* m_cache; - Mutex* m_lock; -}; - -/* - * The actual in-memory session cache implementation. - */ -class MemorySessionCache : public virtual ISessionCache, public virtual Remoted -{ -public: - MemorySessionCache(const DOMElement* e); - virtual ~MemorySessionCache(); - - DDF receive(const DDF& in); - - string insert( - const IApplication* application, - const RoleDescriptor* role, - const char* client_addr, - const SAMLSubject* subject, - const char* authnContext, - const SAMLResponse* tokens - ); - ISessionCacheEntry* find(const char* key, const IApplication* application, const char* client_addr); - void remove(const char* key, const IApplication* application, const char* client_addr); - - void cleanup(); - - bool setBackingStore(ISessionCacheStore* store); - -private: - const DOMElement* m_root; // Only valid during initialization - RWLock* m_lock; - map m_hashtable; - - Category* m_log; - Remoted* restoreInsert; - Remoted* restoreFind; - Remoted* restoreRemove; - ISessionCacheStore* m_sink; - - void dormant(const char* key); - static void* cleanup_fcn(void*); - bool shutdown; - CondWait* shutdown_wait; - Thread* cleanup_thread; - - // extracted config settings - unsigned int m_AATimeout,m_AAConnectTimeout; - unsigned int m_defaultLifetime,m_retryInterval; - bool m_strictValidity,m_propagateErrors,m_writeThrough; - friend class MemorySessionCacheEntry; -}; - -MemorySessionCacheEntry::MemorySessionCacheEntry( - MemorySessionCache* cache, - const char* key, - const IApplication* application, - const RoleDescriptor* role, - const char* client_addr, - const SAMLSubject* subject, - const char* authnContext, - const SAMLResponse* tokens - ) : StubCacheEntry(cache->m_log), m_cache(cache), m_responseExpiration(0), m_lastRetry(0) -{ - m_sessionCreated = m_lastAccess = time(NULL); - - // Store session properties in DDF. - m_obj=DDF(NULL).structure(); - m_obj.addmember("key").string(key); - m_obj.addmember("client_address").string(client_addr); - m_obj.addmember("application_id").string(application->getId()); - xmltooling::auto_ptr_char pid(dynamic_cast(role->getParent())->getEntityID()); - m_obj.addmember("provider_id").string(pid.get()); - m_obj.addmember("major_version").integer(1); - m_obj.addmember("minor_version").integer(tokens->getMinorVersion()); - - // Save the subject as XML. - ostringstream os; - os << *subject; - m_obj.addmember("subject").string(os.str().c_str()); - - // Save the authn method. - m_obj.addmember("authn_context").string(authnContext); - - // Serialize unfiltered assertions. - os.str(""); - os << *tokens; - m_obj.addmember("tokens.unfiltered").string(os.str().c_str()); - - if (hasAttributes(*tokens)) { - // Filter attributes in the response. - auto_ptr filtered(filter(tokens, application, role)); - - // Calculate expiration. - m_responseExpiration=calculateExpiration(*(filtered.get())); - - // Serialize filtered assertions (if changes were made). - os.str(""); - os << *(filtered.get()); - string fstr=os.str(); - if (fstr.length() != m_obj["tokens.unfiltered"].strlen()) - m_obj.addmember("tokens.filtered").string(fstr.c_str()); - - // Save actual objects only if we're running inprocess. The subject needs to be - // owned by the entry, so we'll defer creation of a cloned copy. - if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) { - if (m_obj["tokens.filtered"].isstring()) - m_pFiltered=filtered.release(); - } - } - - m_lock = Mutex::create(); - - if (m_log->isDebugEnabled()) { - m_log->debug("new cache entry created: SessionID (%s) IdP (%s) Address (%s)", key, pid.get(), client_addr); - } - - // Transaction Logging - xmltooling::auto_ptr_char hname(subject->getNameIdentifier()->getName()); - STConfig& stc=static_cast(ShibTargetConfig::getConfig()); - stc.getTransactionLog().infoStream() << - "New session (ID: " << - key << - ") with (applicationId: " << - application->getId() << - ") for principal from (IdP: " << - pid.get() << - ") at (ClientAddress: " << - client_addr << - ") with (NameIdentifier: " << - hname.get() << - ")"; - stc.releaseTransactionLog(); -} - -MemorySessionCacheEntry::MemorySessionCacheEntry( - MemorySessionCache* cache, - const char* key, - const IApplication* application, - const RoleDescriptor* role, - const char* client_addr, - const char* subject, - const char* authnContext, - const char* tokens, - int majorVersion, - int minorVersion, - time_t created, - time_t accessed - ) : StubCacheEntry(cache->m_log), m_cache(cache), m_responseExpiration(0), m_lastRetry(0) -{ - m_sessionCreated = created; - m_lastAccess = accessed; - - // Reconstitute the tokens for filtering. - istringstream is(tokens); - auto_ptr unfiltered(new SAMLResponse(is,minorVersion)); - - // Store session properties in DDF. - m_obj=DDF(NULL).structure(); - m_obj.addmember("key").string(key); - m_obj.addmember("client_address").string(client_addr); - m_obj.addmember("application_id").string(application->getId()); - xmltooling::auto_ptr_char pid(dynamic_cast(role->getParent())->getEntityID()); - m_obj.addmember("provider_id").string(pid.get()); - m_obj.addmember("subject").string(subject); - m_obj.addmember("authn_context").string(authnContext); - m_obj.addmember("tokens.unfiltered").string(tokens); - m_obj.addmember("major_version").integer(majorVersion); - m_obj.addmember("minor_version").integer(minorVersion); - - if (hasAttributes(*(unfiltered.get()))) { - auto_ptr filtered(filter(unfiltered.get(), application, role)); - - // Calculate expiration. - m_responseExpiration=calculateExpiration(*(filtered.get())); - - // Serialize filtered assertions (if changes were made). - ostringstream os; - os << *(filtered.get()); - string fstr=os.str(); - if (fstr.length() != strlen(tokens)) - m_obj.addmember("tokens.filtered").string(fstr.c_str()); - - // Save actual objects only if we're running inprocess. - if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) { - m_pUnfiltered=unfiltered.release(); - if (m_obj["tokens.filtered"].isstring()) - m_pFiltered=filtered.release(); - } - } - - m_lock = Mutex::create(); - - if (m_log->isDebugEnabled()) - m_log->debug("session loaded from secondary cache (ID: %s)", key); -} - - -MemorySessionCacheEntry::~MemorySessionCacheEntry() -{ - delete m_lock; -} - -HRESULT MemorySessionCacheEntry::isValid(const IApplication* app, const char* client_addr) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("isValid"); -#endif - - // Obtain validation rules from application settings. - bool consistentIPAddress=true; - int lifetime=0,timeout=0; - const PropertySet* props=app->getPropertySet("Sessions"); - if (props) { - pair p=props->getUnsignedInt("lifetime"); - if (p.first) - lifetime = p.second; - p=props->getUnsignedInt("timeout"); - if (p.first) - timeout = p.second; - pair pcheck=props->getBool("consistentIPAddress"); - if (pcheck.first) - consistentIPAddress = pcheck.second; - } - - if (m_log->isDebugEnabled()) - m_log->debug("checking validity of session (ID: %s)", m_obj["key"].string()); - - time_t now=time(NULL); - if (lifetime > 0 && now > m_sessionCreated+lifetime) { - if (m_log->isInfoEnabled()) - m_log->info("session expired (ID: %s)", m_obj["key"].string()); - return SESSION_E_EXPIRED; - } - - if (timeout > 0 && now-m_lastAccess >= timeout) { - // May need to query sink first to find out if another cluster member has been used. - if (m_cache->m_sink && m_cache->m_writeThrough) { - if (NOERROR!=m_cache->m_sink->onRead(m_obj["key"].string(),m_lastAccess)) - m_log->error("cache store failed to return last access timestamp"); - if (now-m_lastAccess >= timeout) { - m_log->info("session timed out (ID: %s)", m_obj["key"].string()); - return SESSION_E_EXPIRED; - } - } - else { - m_log->info("session timed out (ID: %s)", m_obj["key"].string()); - return SESSION_E_EXPIRED; - } - } - - if (consistentIPAddress) { - if (m_log->isDebugEnabled()) - m_log->debug("comparing client address %s against %s", client_addr, getClientAddress()); - if (strcmp(client_addr, getClientAddress())) { - m_log->debug("client address mismatch"); - return SESSION_E_ADDRESSMISMATCH; - } - } - - m_lastAccess=now; - - if (m_cache->m_sink && m_cache->m_writeThrough && timeout > 0) { - // Update sink with last access data, if possible. - if (FAILED(m_cache->m_sink->onUpdate(m_obj["key"].string(),NULL,m_lastAccess))) - m_log->error("cache store failed to update last access timestamp"); - } - - return NOERROR; -} - -bool MemorySessionCacheEntry::hasAttributes(const SAMLResponse& r) const -{ - Iterator assertions=r.getAssertions(); - while (assertions.hasNext()) { - Iterator statements=assertions.next()->getStatements(); - while (statements.hasNext()) { - if (dynamic_cast(statements.next())) - return true; - } - } - return false; -} - -time_t MemorySessionCacheEntry::calculateExpiration(const SAMLResponse& r) const -{ - time_t expiration=0; - Iterator assertions = r.getAssertions(); - while (assertions.hasNext()) { - SAMLAssertion* assertion = assertions.next(); - - // Only examine this assertion if it contains an attribute statement. - // We know at least one such statement exists, or this is a query response. - Iterator statements = assertion->getStatements(); - while (statements.hasNext()) { - if (dynamic_cast(statements.next())) { - const SAMLDateTime* thistime = assertion->getNotOnOrAfter(); - - // If there is no time, then just continue and ignore this assertion. - if (thistime) { - // If this is a tighter expiration, cache it. - if (expiration == 0 || thistime->getEpoch() < expiration) - expiration = thistime->getEpoch(); - } - - // No need to continue with this assertion. - break; - } - } - } - - // If we didn't find any assertions with times, then use the default. - if (expiration == 0) - expiration = time(NULL) + m_cache->m_defaultLifetime; - - return expiration; -} - -void MemorySessionCacheEntry::populate(const IApplication* application, const EntityDescriptor* source, bool initial) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("populate"); -#endif - - // Do we have any attribute data cached? - if (m_responseExpiration > 0) { - // Can we use what we have? - if (time(NULL) < m_responseExpiration) - return; - - // Possibly check the sink in case another cluster member already refreshed it. - if (m_cache->m_sink && m_cache->m_writeThrough) { - string tokensFromSink; - HRESULT hr=m_cache->m_sink->onRead(m_obj["key"].string(),tokensFromSink); - if (FAILED(hr)) - m_log->error("cache store failed to return updated tokens"); - else if (hr==NOERROR && tokensFromSink!=m_obj["tokens.unfiltered"].string()) { - - // Bah...find role again. - const RoleDescriptor* role=source->getAttributeAuthorityDescriptor(samlconstants::SAML11_PROTOCOL_ENUM); - if (!role) - role=source->getAttributeAuthorityDescriptor(samlconstants::SAML10_PROTOCOL_ENUM); - if (!role) - role=source->getIDPSSODescriptor(samlconstants::SAML11_PROTOCOL_ENUM); - if (!role) - role=source->getIDPSSODescriptor(samlconstants::SAML10_PROTOCOL_ENUM); - if (!role) { - throw MetadataException("Unable to locate attribute-issuing role in metadata."); - } - - // The tokens in the sink were different. - istringstream is(tokensFromSink); - auto_ptr respFromSink(new SAMLResponse(is,m_obj["minor_version"].integer())); - auto_ptr filteredFromSink(filter(respFromSink.get(),application,role)); - time_t expFromSink=calculateExpiration(*(filteredFromSink.get())); - - // Recheck to see if the new tokens are valid. - if (expFromSink < time(NULL)) { - m_log->info("loading replacement tokens into memory from cache store"); - m_obj["tokens"].destroy(); - delete m_pUnfiltered; - delete m_pFiltered; - m_pUnfiltered=m_pFiltered=NULL; - m_obj.addmember("tokens.unfiltered").string(tokensFromSink.c_str()); - - // Serialize filtered assertions (if changes were made). - ostringstream os; - os << *(filteredFromSink.get()); - string fstr=os.str(); - if (fstr.length() != m_obj.getmember("tokens.unfiltered").strlen()) - m_obj.addmember("tokens.filtered").string(fstr.c_str()); - - // Save actual objects only if we're running inprocess. - if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) { - m_pUnfiltered=respFromSink.release(); - if (m_obj["tokens.filtered"].isstring()) - m_pFiltered=filteredFromSink.release(); - } - - m_responseExpiration=expFromSink; - m_lastRetry=0; - return; - } - } - } - - // If we're being strict, dump what we have and reset timestamps. - if (m_cache->m_strictValidity) { - m_log->info("strictly enforcing attribute validity, dumping expired data"); - m_obj["tokens"].destroy(); - delete m_pUnfiltered; - delete m_pFiltered; - m_pUnfiltered=m_pFiltered=NULL; - m_responseExpiration=0; - m_lastRetry=0; - if (m_cache->m_sink) { - if (FAILED(m_cache->m_sink->onUpdate(m_obj["key"].string(),""))) - m_log->error("cache store returned failure while clearing tokens from entry"); - } - } - } - - try { - pair new_responses=getNewResponse(application,source); - auto_ptr r1(new_responses.first),r2(new_responses.second); - if (new_responses.first) { - m_obj["tokens"].destroy(); - delete m_pUnfiltered; - delete m_pFiltered; - m_pUnfiltered=m_pFiltered=NULL; - m_responseExpiration=0; - - // Serialize unfiltered assertions. - ostringstream os; - os << *new_responses.first; - m_obj.addmember("tokens.unfiltered").string(os.str().c_str()); - - // Serialize filtered assertions (if changes were made). - os.str(""); - os << *new_responses.second; - string fstr=os.str(); - if (fstr.length() != m_obj.getmember("tokens.unfiltered").strlen()) - m_obj.addmember("tokens.filtered").string(fstr.c_str()); - - // Update expiration. - m_responseExpiration=calculateExpiration(*new_responses.second); - - // Save actual objects only if we're running inprocess. - if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) { - m_pUnfiltered=r1.release(); - if (m_obj["tokens.filtered"].isstring()) - m_pFiltered=r2.release(); - } - - // Update backing store. - if (!initial && m_cache->m_sink) { - if (FAILED(m_cache->m_sink->onUpdate(m_obj["key"].string(),m_obj["tokens.unfiltered"].string()))) - m_log->error("cache store returned failure while updating tokens in entry"); - } - - m_lastRetry=0; - m_log->debug("fetched and stored new response"); - STConfig& stc=static_cast(ShibTargetConfig::getConfig()); - stc.getTransactionLog().infoStream() << "Successful attribute query for session (ID: " << m_obj["key"].string() << ")"; - stc.releaseTransactionLog(); - } - } - catch (exception&) { - if (m_cache->m_propagateErrors) - throw; - m_log->warn("suppressed exception caught while trying to fetch attributes"); - } -#ifndef _DEBUG - catch (...) { - if (m_cache->m_propagateErrors) - throw; - m_log->warn("suppressed unknown exception caught while trying to fetch attributes"); - } -#endif -} - -pair MemorySessionCacheEntry::getNewResponse( - const IApplication* application, const EntityDescriptor* source - ) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("getNewResponse"); -#endif - - // The retryInterval determines how often to poll an AA that might be down. - time_t now=time(NULL); - if ((now - m_lastRetry) < m_cache->m_retryInterval) - return pair(NULL,NULL); - if (m_lastRetry) - m_log->debug("retry interval exceeded, trying for attributes again"); - m_lastRetry=now; - - m_log->info("trying to get new attributes for session (ID: %s)", m_obj["key"].string()); - - // Transaction Logging - STConfig& stc=static_cast(ShibTargetConfig::getConfig()); - stc.getTransactionLog().infoStream() << - "Making attribute query for session (ID: " << - m_obj["key"].string() << - ") on (applicationId: " << - m_obj["application_id"].string() << - ") for principal from (IdP: " << - m_obj["provider_id"].string() << - ")"; - stc.releaseTransactionLog(); - - - pair providerID=application->getXMLString("providerId"); - if (!providerID.first) { - m_log->crit("unable to determine ProviderID for application, not set?"); - throw ConfigurationException("Unable to determine ProviderID for application, not set?"); - } - - // Try to locate an AA role. - const AttributeAuthorityDescriptor* AA=source->getAttributeAuthorityDescriptor( - m_obj["minor_version"].integer()==1 ? samlconstants::SAML11_PROTOCOL_ENUM : samlconstants::SAML10_PROTOCOL_ENUM - ); - if (!AA) { - m_log->warn("unable to locate metadata for identity provider's Attribute Authority"); - return pair(NULL,NULL); - } - - // Get protocol signing policy. - const PropertySet* credUse=application->getCredentialUse(source); - pair signRequest=credUse ? credUse->getBool("signRequest") : make_pair(false,false); - pair signatureAlg=credUse ? credUse->getString("signatureAlg") : pair(false,NULL); - if (!signatureAlg.first) - signatureAlg.second=URI_ID_RSA_SHA1; - pair digestAlg=credUse ? credUse->getString("digestAlg") : pair(false,NULL); - if (!digestAlg.first) - digestAlg.second=URI_ID_SHA1; - pair signedResponse=credUse ? credUse->getBool("signedResponse") : make_pair(false,false); - pair signingCred=credUse ? credUse->getString("Signing") : pair(false,NULL); - - SAMLResponse* response = NULL; - try { - // Copy NameID from subject (may need to reconstitute it). - SAMLNameIdentifier* nameid=NULL; - if (m_pSubject) - nameid=static_cast(m_pSubject->getNameIdentifier()->clone()); - else { - istringstream instr(m_obj["subject"].string()); - auto_ptr sub(new SAMLSubject(instr)); - nameid=static_cast(sub->getNameIdentifier()->clone()); - } - - // Build a SAML Request.... - SAMLAttributeQuery* q=new SAMLAttributeQuery( - new SAMLSubject(nameid), - providerID.second - ); - auto_ptr req(new SAMLRequest(q)); - req->setMinorVersion(m_obj["minor_version"].integer()); - - // Sign it? - if (signRequest.first && signRequest.second && signingCred.first) { - if (req->getMinorVersion()==1) { - CredentialResolver* cr=SPConfig::getConfig().getServiceProvider()->getCredentialResolver(signingCred.second); - if (cr) { - xmltooling::Locker locker(cr); - req->sign(cr->getKey(),cr->getCertificates(),signatureAlg.second,digestAlg.second); - } - else - m_log->error("unable to sign attribute query, specified credential (%s) was not found",signingCred.second); - } - else - m_log->error("unable to sign SAML 1.0 attribute query, only SAML 1.1 defines signing adequately"); - } - - m_log->debug("trying to query an AA..."); - - // Call context object - ShibHTTPHook::ShibHTTPHookCallContext ctx(credUse,AA); - - // Use metadata to locate endpoints. - const vector& endpoints=AA->getAttributeServices(); - for (vector::const_iterator ep=endpoints.begin(); !response && ep!=endpoints.end(); ++ep) { - try { - // Get a binding object for this protocol. - const SAMLBinding* binding = application->getBinding((*ep)->getBinding()); - if (!binding) { - xmltooling::auto_ptr_char prot((*ep)->getBinding()); - m_log->warn("skipping binding on unsupported protocol (%s)", prot.get()); - continue; - } - static const XMLCh https[] = {chLatin_h, chLatin_t, chLatin_t, chLatin_p, chLatin_s, chColon, chNull}; - auto_ptr r(binding->send((*ep)->getLocation(), *(req.get()), &ctx)); - if (r->isSigned()) { - // TODO: trust stuff will be changing anyway... - //if (!t.validate(*r,AA)) - // throw TrustException("Unable to verify signed response message."); - } - else if (!ctx.isAuthenticated() || XMLString::compareNString((*ep)->getLocation(),https,6)) - throw XMLSecurityException("Response message was unauthenticated."); - response = r.release(); - } - catch (exception& e) { - m_log->error("caught exception during SAML attribute query: %s", e.what()); - } - } - - if (response) { - if (signedResponse.first && signedResponse.second && !response->isSigned()) { - delete response; - m_log->error("unsigned response obtained, but we were told it must be signed."); - throw XMLSecurityException("Unable to obtain a signed response message."); - } - - // Iterate over the tokens and apply basic validation. - time_t now=time(NULL); - Iterator assertions=response->getAssertions(); - for (unsigned int a=0; agetEntityID(),assertions[a]->getIssuer())) { - xmltooling::auto_ptr_char bad(assertions[a]->getIssuer()); - m_log->warn("discarding assertion not issued by (%s), instead by (%s)",m_obj["provider_id"].string(),bad.get()); - response->removeAssertion(a); - continue; - } - - // Validate the token. - try { - application->validateToken(assertions[a],now,AA,application->getTrustEngine()); - a++; - } - catch (exception&) { - m_log->warn("assertion failed to validate, removing it from response"); - response->removeAssertion(a); - } - } - - // Run it through the filter. - return make_pair(response,filter(response,application,AA)); - } - } - catch (exception& e) { - m_log->error("caught exception during query to AA: %s", e.what()); - throw; - } - - m_log->error("no response obtained"); - return pair(NULL,NULL); -} - -SAMLResponse* MemorySessionCacheEntry::filter( - const SAMLResponse* r, const IApplication* application, const RoleDescriptor* role - ) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("filter"); -#endif - - // Make a copy of the original and process that against the AAP. - auto_ptr copy(static_cast(r->clone())); - copy->toDOM(); - - Iterator copies=copy->getAssertions(); - for (unsigned long j=0; j < copies.size();) { - try { - // Finally, filter the content. - shibboleth::AAP::apply(application->getAAPProviders(),*(copies[j]),role); - j++; - - } - catch (exception&) { - m_log->info("no statements remain after AAP, removing assertion"); - copy->removeAssertion(j); - } - } - - // Audit the results. - STConfig& stc=static_cast(ShibTargetConfig::getConfig()); - Category& tran=stc.getTransactionLog(); - if (tran.isInfoEnabled()) { - tran.infoStream() << - "Caching the following attributes after AAP applied for session (ID: " << - m_obj["key"].string() << - ") on (applicationId: " << - m_obj["application_id"].string() << - ") for principal from (IdP: " << - m_obj["provider_id"].string() << - ") {"; - - Iterator loggies=copy->getAssertions(); - while (loggies.hasNext()) { - SAMLAssertion* logit=loggies.next(); - Iterator states=logit->getStatements(); - while (states.hasNext()) { - SAMLAttributeStatement* state=dynamic_cast(states.next()); - Iterator attrs=state ? state->getAttributes() : EMPTY(SAMLAttribute*); - while (attrs.hasNext()) { - SAMLAttribute* attr=attrs.next(); - xmltooling::auto_ptr_char attrname(attr->getName()); - tran.infoStream() << "\t" << attrname.get() << " (" << attr->getValues().size() << " values)"; - } - } - } - tran.info("}"); - } - stc.releaseTransactionLog(); - - return copy.release(); -} - -MemorySessionCache::MemorySessionCache(const DOMElement* e) - : m_root(e), m_AATimeout(30), m_AAConnectTimeout(15), m_defaultLifetime(1800), m_retryInterval(300), - m_strictValidity(true), m_propagateErrors(false), m_writeThrough(false), m_lock(RWLock::create()), - m_log(&Category::getInstance(SHIBT_LOGCAT".SessionCache")), - restoreInsert(NULL), restoreFind(NULL), restoreRemove(NULL), m_sink(NULL) -{ - if (m_root) { - const XMLCh* tag=m_root->getAttributeNS(NULL,AATimeout); - if (tag && *tag) { - m_AATimeout = XMLString::parseInt(tag); - if (!m_AATimeout) - m_AATimeout=30; - } - - tag=m_root->getAttributeNS(NULL,AAConnectTimeout); - if (tag && *tag) { - m_AAConnectTimeout = XMLString::parseInt(tag); - if (!m_AAConnectTimeout) - m_AAConnectTimeout=15; - } - - tag=m_root->getAttributeNS(NULL,defaultLifetime); - if (tag && *tag) { - m_defaultLifetime = XMLString::parseInt(tag); - if (!m_defaultLifetime) - m_defaultLifetime=1800; - } - - tag=m_root->getAttributeNS(NULL,retryInterval); - if (tag && *tag) { - m_retryInterval = XMLString::parseInt(tag); - if (!m_retryInterval) - m_retryInterval=300; - } - - tag=m_root->getAttributeNS(NULL,strictValidity); - if (tag && (*tag==chDigit_0 || *tag==chLatin_f)) - m_strictValidity=false; - - tag=m_root->getAttributeNS(NULL,propagateErrors); - if (tag && (*tag==chDigit_1 || *tag==chLatin_t)) - m_propagateErrors=true; - - tag=m_root->getAttributeNS(NULL,writeThrough); - if (tag && (*tag==chDigit_1 || *tag==chLatin_t)) - m_writeThrough=true; - } - - SAMLConfig::getConfig().timeout = m_AATimeout; - SAMLConfig::getConfig().conn_timeout = m_AAConnectTimeout; - - // Register for remoted messages. - ListenerService* listener=SPConfig::getConfig().getServiceProvider()->getListenerService(false); - if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) { - restoreInsert=listener->regListener("SessionCache::insert",this); - restoreFind=listener->regListener("SessionCache::find",this); - restoreRemove=listener->regListener("SessionCache::remove",this); - } - else - m_log->info("no listener interface available, cache remoting is disabled"); - - shutdown_wait = CondWait::create(); - shutdown = false; - cleanup_thread = Thread::create(&cleanup_fcn, (void*)this); -} - -MemorySessionCache::~MemorySessionCache() -{ - // Shut down the cleanup thread and let it know... - shutdown = true; - shutdown_wait->signal(); - cleanup_thread->join(NULL); - - // Unregister remoted messages. - ListenerService* listener=SPConfig::getConfig().getServiceProvider()->getListenerService(false); - if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) { - listener->unregListener("SessionCache::insert",this,restoreInsert); - listener->unregListener("SessionCache::find",this,restoreFind); - listener->unregListener("SessionCache::remove",this,restoreRemove); - } - - for_each(m_hashtable.begin(),m_hashtable.end(),xmltooling::cleanup_pair()); - delete m_lock; - delete shutdown_wait; -} - -bool MemorySessionCache::setBackingStore(ISessionCacheStore* store) -{ - if (m_sink && store!=m_sink) - return false; - m_sink=store; - return true; -} - -/* - * IPC message definitions: - * - * SessionCache::insert - * - * IN - * application_id - * client_address - * provider_id - * major_version - * minor_version - * authn_context - * subject - * tokens.unfiltered - * - * OUT - * key - * - * SessionCache::find - * - * IN - * key - * application_id - * client_address - * - * OUT - * client_address - * provider_id - * major_version - * minor_version - * authn_context - * subject - * tokens.unfiltered - * tokens.filtered - * - * SessionCache::remove - * - * IN - * key - * application_id - * client_address - */ - -DDF MemorySessionCache::receive(const DDF& in) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("receive"); -#endif - - // Find application. - xmltooling::Locker confLocker(SPConfig::getConfig().getServiceProvider()); - const char* aid=in["application_id"].string(); - const IApplication* app=aid ? dynamic_cast(SPConfig::getConfig().getServiceProvider()->getApplication(aid)) : NULL; - if (!app) { - // Something's horribly wrong. - m_log->error("couldn't find application (%s) for session", aid ? aid : "(missing)"); - throw ConfigurationException("Unable to locate application for session, deleted?"); - } - - if (!strcmp(in.name(),"SessionCache::find")) { - // Check required parameters. - const char* key=in["key"].string(); - const char* client_address=in["client_address"].string(); - if (!key || !client_address) - throw SAMLException("Required parameters missing in call to SessionCache::find"); - - try { - // Lookup the session and cast down to the internal type. - MemorySessionCacheEntry* entry=dynamic_cast(find(key,app,client_address)); - if (!entry) - return DDF(); - DDF dup=entry->getDDF().copy(); - entry->unlock(); - return dup; - } - catch (exception&) { - remove(key,app,client_address); - throw; - } - } - else if (!strcmp(in.name(),"SessionCache::remove")) { - // Check required parameters. - const char* key=in["key"].string(); - const char* client_address=in["client_address"].string(); - if (!key || !client_address) - throw SAMLException("Required parameters missing in call to SessionCache::remove"); - - remove(key,app,client_address); - return DDF(); - } - else if (!strcmp(in.name(),"SessionCache::insert")) { - // Check required parameters. - const char* client_address=in["client_address"].string(); - const char* provider_id=in["provider_id"].string(); - const char* authn_context=in["authn_context"].string(); - const char* subject=in["subject"].string(); - const char* tokens=in["tokens.unfiltered"].string(); - if (!client_address || !provider_id || !authn_context || !subject || !tokens) - throw SAMLException("Required parameters missing in call to SessionCache::insert"); - int minor=in["minor_version"].integer(); - - // Locate entity descriptor to use in filtering. - MetadataProvider* m=app->getMetadataProvider(); - xmltooling::Locker locker(m); - const EntityDescriptor* site=m->getEntityDescriptor(provider_id); - if (!site) { - m_log->error("unable to locate issuing identity provider's metadata"); - throw MetadataException("Unable to locate identity provider's metadata."); - } - const RoleDescriptor* role=site->getAttributeAuthorityDescriptor(samlconstants::SAML11_PROTOCOL_ENUM); - if (!role) - role=site->getAttributeAuthorityDescriptor(samlconstants::SAML10_PROTOCOL_ENUM); - if (!role) - role=site->getIDPSSODescriptor(samlconstants::SAML11_PROTOCOL_ENUM); - if (!role) - role=site->getIDPSSODescriptor(samlconstants::SAML10_PROTOCOL_ENUM); - if (!role) { - m_log->error("unable to locate attribute-issuing role in identity provider's metadata"); - throw MetadataException("Unable to locate attribute-issuing role in identity provider's metadata."); - } - - // Deserialize XML for insert method. - istringstream subis(subject); - auto_ptr pSubject(new SAMLSubject(subis)); - istringstream tokis(tokens); - auto_ptr pTokens(new SAMLResponse(tokis,minor)); - - // Insert the data and return the cache key. - string key=insert(app,role,client_address,pSubject.get(),authn_context,pTokens.get()); - - DDF out(NULL); - out.structure(); - out.addmember("key").string(key.c_str()); - return out; - } - throw ListenerException("Unsupported operation ($1)",xmltooling::params(1,in.name())); -} - -string MemorySessionCache::insert( - const IApplication* application, - const RoleDescriptor* role, - const char* client_addr, - const SAMLSubject* subject, - const char* authnContext, - const SAMLResponse* tokens - ) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("insert"); -#endif - - SAMLIdentifier id; - xmltooling::auto_ptr_char key(id); - - if (m_log->isDebugEnabled()) - m_log->debug("creating new cache entry for application %s: \"%s\"", application->getId(), key.get()); - - auto_ptr entry( - new MemorySessionCacheEntry( - this, - key.get(), - application, - role, - client_addr, - subject, - authnContext, - tokens - ) - ); - entry->populate(application,dynamic_cast(role->getParent()),true); - - if (m_sink) { - HRESULT hr=m_sink->onCreate(key.get(),application,entry.get(),1,tokens->getMinorVersion(),entry->created()); - if (FAILED(hr)) { - m_log->error("cache store returned failure while storing new entry"); - throw IOException("Unable to record new session in cache store."); - } - } - - m_lock->wrlock(); - m_hashtable[key.get()]=entry.release(); - m_lock->unlock(); - - return key.get(); -} - -ISessionCacheEntry* MemorySessionCache::find(const char* key, const IApplication* application, const char* client_addr) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("find"); -#endif - - m_log->debug("searching memory cache for key (%s)", key); - m_lock->rdlock(); - - map::const_iterator i=m_hashtable.find(key); - if (i==m_hashtable.end()) { - m_lock->unlock(); - m_log->debug("no match found"); - if (!m_sink) - return NULL; // no backing store to search - - m_log->debug("searching backing store"); - string appid,addr,pid,sub,ac,tokens; - int major,minor; - time_t created,accessed; - HRESULT hr=m_sink->onRead(key,appid,addr,pid,sub,ac,tokens,major,minor,created,accessed); - if (hr==S_FALSE) - return NULL; - else if (FAILED(hr)) { - m_log->error("cache store returned failure during search"); - return NULL; - } - const IApplication* eapp=dynamic_cast(SPConfig::getConfig().getServiceProvider()->getApplication(appid.c_str())); - if (!eapp) { - // Something's horribly wrong. - m_log->error("couldn't find application (%s) for session", appid.c_str()); - if (FAILED(m_sink->onDelete(key))) - m_log->error("cache store returned failure during delete"); - return NULL; - } - if (m_log->isDebugEnabled()) - m_log->debug("loading cache entry (ID: %s) back into memory for application (%s)", key, appid.c_str()); - - // Locate role to use in filtering. - MetadataProvider* m=eapp->getMetadataProvider(); - xmltooling::Locker locker(m); - const EntityDescriptor* site=m->getEntityDescriptor(pid.c_str()); - if (!site) { - m_log->error("unable to locate issuing identity provider's metadata"); - if (FAILED(m_sink->onDelete(key))) - m_log->error("cache store returned failure during delete"); - return NULL; - } - const RoleDescriptor* role=site->getAttributeAuthorityDescriptor(samlconstants::SAML11_PROTOCOL_ENUM); - if (!role) - role=site->getAttributeAuthorityDescriptor(samlconstants::SAML10_PROTOCOL_ENUM); - if (!role) - role=site->getIDPSSODescriptor(samlconstants::SAML11_PROTOCOL_ENUM); - if (!role) - role=site->getIDPSSODescriptor(samlconstants::SAML10_PROTOCOL_ENUM); - if (!role) { - m_log->error("unable to locate attribute-issuing role in identity provider's metadata"); - if (FAILED(m_sink->onDelete(key))) - m_log->error("cache store returned failure during delete"); - return NULL; - } - - MemorySessionCacheEntry* entry = new MemorySessionCacheEntry( - this, - key, - eapp, - role, - addr.c_str(), - sub.c_str(), - ac.c_str(), - tokens.c_str(), - major, - minor, - created, - accessed - ); - m_lock->wrlock(); - m_hashtable[key]=entry; - m_lock->unlock(); - - // Downgrade to a read lock and repeat the initial search. - m_lock->rdlock(); - i=m_hashtable.find(key); - if (i==m_hashtable.end()) { - m_lock->unlock(); - m_log->warn("cache entry was loaded from backing store, but disappeared after lock downgrade"); - return NULL; - } - } - else - m_log->debug("match found"); - - // Check for application mismatch (could also do this with partitioned caches by application ID) - if (!i->second->checkApplication(application)) { - m_lock->unlock(); - m_log->crit("An application (%s) attempted to access another application's session!", application->getId()); - return NULL; - } - - // Check for timeouts, expiration, address mismatch, etc (also updates last access) - // Use the return code to assign specific error messages. - try { - HRESULT hr=i->second->isValid(application, client_addr); - if (FAILED(hr)) { - MetadataProvider* m=application->getMetadataProvider(); - xmltooling::Locker locker(m); - switch (hr) { - case SESSION_E_EXPIRED: { - opensaml::RetryableProfileException ex("Your session has expired, and you must re-authenticate."); - annotateException(&ex,m->getEntityDescriptor(i->second->getProviderId(),false)); // throws it - } - - case SESSION_E_ADDRESSMISMATCH: { - opensaml::RetryableProfileException ex( - "Your IP address ($1) does not match the address recorded at the time the session was established.", - xmltooling::params(1,client_addr) - ); - annotateException(&ex,m->getEntityDescriptor(i->second->getProviderId(),false)); // throws it - } - - default: { - opensaml::RetryableProfileException ex("Your session is invalid."); - annotateException(&ex,m->getEntityDescriptor(i->second->getProviderId(),false)); // throws it - } - } - } - } - catch (...) { - m_lock->unlock(); - throw; - } - - // Lock the cache entry for the caller -- they have to unlock it. - i->second->lock(); - m_lock->unlock(); - - try { - // Make sure the entry has valid tokens. - MetadataProvider* m=application->getMetadataProvider(); - xmltooling::Locker locker(m); - i->second->populate(application,m->getEntityDescriptor(i->second->getProviderId())); - } - catch (...) { - i->second->unlock(); - throw; - } - - return i->second; -} - -void MemorySessionCache::remove(const char* key, const IApplication* application, const char* client_addr) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("remove"); -#endif - - m_log->debug("removing cache entry with key (%s)", key); - - // lock the cache for writing, which means we know nobody is sitting in find() - m_lock->wrlock(); - - // grab the entry from the database. - map::const_iterator i=m_hashtable.find(key); - if (i==m_hashtable.end()) { - m_lock->unlock(); - return; - } - - // ok, remove the entry and lock it - MemorySessionCacheEntry* entry=i->second; - m_hashtable.erase(key); - entry->lock(); - - // unlock the cache - m_lock->unlock(); - - entry->unlock(); - - // Notify sink. Smart ptr will make sure entry gets deleted. - auto_ptr entrywrap(entry); - if (m_sink) { - if (FAILED(m_sink->onDelete(key))) - m_log->error("cache store failed to delete entry"); - } - - // Transaction Logging - STConfig& stc=static_cast(ShibTargetConfig::getConfig()); - stc.getTransactionLog().infoStream() << "Destroyed session (ID: " << key << ")"; - stc.releaseTransactionLog(); -} - -void MemorySessionCache::dormant(const char* key) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("dormant"); -#endif - - m_log->debug("purging old cache entry with key (%s)", key); - - // lock the cache for writing, which means we know nobody is sitting in find() - m_lock->wrlock(); - - // grab the entry from the database. - map::const_iterator i=m_hashtable.find(key); - if (i==m_hashtable.end()) { - m_lock->unlock(); - return; - } - - // ok, remove the entry and lock it - MemorySessionCacheEntry* entry=i->second; - m_hashtable.erase(key); - entry->lock(); - - // unlock the cache - m_lock->unlock(); - - // we can release the cache entry lock because we know we're not in the cache anymore - entry->unlock(); - - auto_ptr entrywrap(entry); - if (m_sink && !m_writeThrough) { - // Update sink with last access data. Wrapper will make sure entry gets deleted. - if (FAILED(m_sink->onUpdate(key,NULL,entry->lastAccess()))) - m_log->error("cache store failed to update last access timestamp"); - } -} - -void MemorySessionCache::cleanup() -{ -#ifdef _DEBUG - xmltooling::NDC ndc("cleanup()"); -#endif - - int rerun_timer = 0; - int timeout_life = 0; - Mutex* mutex = Mutex::create(); - - // Load our configuration details... - const XMLCh* tag=m_root->getAttributeNS(NULL,cleanupInterval); - if (tag && *tag) - rerun_timer = XMLString::parseInt(tag); - - tag=m_root->getAttributeNS(NULL,cacheTimeout); - if (tag && *tag) - timeout_life = XMLString::parseInt(tag); - - if (rerun_timer <= 0) - rerun_timer = 300; // rerun every 5 minutes - - if (timeout_life <= 0) - timeout_life = 28800; // timeout after 8 hours - - mutex->lock(); - - m_log->info("cleanup thread started...Run every %d secs; timeout after %d secs", rerun_timer, timeout_life); - - while (!shutdown) { - shutdown_wait->timedwait(mutex,rerun_timer); - if (shutdown) - break; - - // Ok, let's run through the cleanup process and clean out - // really old sessions. This is a two-pass process. The - // first pass is done holding a read-lock while we iterate over - // the cache. The second pass doesn't need a lock because - // the 'deletes' will lock the cache. - - // Pass 1: iterate over the map and find all entries that have not been - // used in X hours - vector stale_keys; - time_t stale = time(NULL) - timeout_life; - - m_lock->rdlock(); - for (map::const_iterator i=m_hashtable.begin(); i!=m_hashtable.end(); i++) - { - // If the last access was BEFORE the stale timeout... - i->second->lock(); - time_t last=i->second->lastAccess(); - i->second->unlock(); - if (last < stale) - stale_keys.push_back(i->first); - } - m_lock->unlock(); - - if (!stale_keys.empty()) { - m_log->info("purging %d old sessions", stale_keys.size()); - - // Pass 2: walk through the list of stale entries and remove them from the cache - for (vector::const_iterator j = stale_keys.begin(); j != stale_keys.end(); j++) - dormant(j->c_str()); - } - } - - m_log->info("cleanup thread finished."); - - mutex->unlock(); - delete mutex; - Thread::exit(NULL); -} - -void* MemorySessionCache::cleanup_fcn(void* cache_p) -{ - MemorySessionCache* cache = reinterpret_cast(cache_p); - -#ifndef WIN32 - // First, let's block all signals - Thread::mask_all_signals(); -#endif - - // Now run the cleanup process. - cache->cleanup(); - return NULL; -} - -SessionCache* MemoryCacheFactory(const DOMElement* const & e) -{ - // If this is a long-lived process, we return the "real" cache. - if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) - return new MemorySessionCache(e); - // Otherwise, we return a stubbed front-end that remotes calls to the real cache. - return new StubCache(e); -} diff --git a/shib-target/shib-config.cpp b/shib-target/shib-config.cpp deleted file mode 100644 index 382c91f..0000000 --- a/shib-target/shib-config.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shib-config.cpp -- ShibTarget initialization and finalization routines - * - * Created By: Derek Atkins - * - * $Id$ - */ - -#include "internal.h" -#include -#include - -#include - -using namespace shibsp; -using namespace shibtarget; -using namespace shibboleth; -using namespace saml; -using namespace log4cpp; -using namespace std; - -using xmltooling::XMLToolingConfig; -using xmltooling::PluginManager; - -namespace { - STConfig g_Config; -} - -// Factories for built-in plugins we can manufacture. Actual definitions -// will be with the actual object implementation. -#ifndef WIN32 -PlugManager::Factory UnixListenerFactory; -#endif -PlugManager::Factory TCPListenerFactory; -//PlugManager::Factory MemoryListenerFactory; - -PluginManager::Factory ShibSessionInitiatorFactory; -PluginManager::Factory SAML1POSTFactory; -PluginManager::Factory SAML1ArtifactFactory; -PluginManager::Factory ShibLogoutFactory; - -ShibTargetConfig& ShibTargetConfig::getConfig() -{ - return g_Config; -} - -bool STConfig::init(const char* schemadir) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("init"); -#endif - Category& log = Category::getInstance(SHIBT_LOGCAT".Config"); - - if (!schemadir) { - log.fatal("XML schema directory not supplied"); - return false; - } - - // This will cause some extra console logging, but for now, - // initialize the underlying libraries. - SAMLConfig& samlConf=SAMLConfig::getConfig(); - if (schemadir) - samlConf.schema_dir = schemadir; - if (!samlConf.init()) { - log.fatal("failed to initialize OpenSAML1 library"); - return false; - } - - ShibConfig& shibConf=ShibConfig::getConfig(); - if (!shibConf.init()) { - log.fatal("Failed to initialize Shib library"); - samlConf.term(); - return false; - } - - SPConfig& conf=SPConfig::getConfig(); - if (!SPConfig::getConfig().init(NULL)) { - log.fatal("Failed to initialize SP library"); - shibConf.term(); - samlConf.term(); - return false; - } - - // Register built-in plugin types. - conf.ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory); - - conf.SessionInitiatorManager.registerFactory(shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI,&ShibSessionInitiatorFactory); - conf.AssertionConsumerServiceManager.registerFactory(samlconstants::SAML1_PROFILE_BROWSER_POST,&SAML1POSTFactory); - conf.AssertionConsumerServiceManager.registerFactory(samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT,&SAML1ArtifactFactory); - conf.SingleLogoutServiceManager.registerFactory(shibspconstants::SHIB1_LOGOUT_PROFILE_URI,&ShibLogoutFactory); - - log.info("finished initializing"); - return true; -} - -bool STConfig::load(const char* config) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("load"); -#endif - Category& log = Category::getInstance(SHIBT_LOGCAT".Config"); - - if (!config) { - log.fatal("path to configuration file not supplied"); - shutdown(); - return false; - } - - try { - log.info("loading configuration file: %s", config); - static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h); - DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(NULL); - DOMDocument* dummydoc=impl->createDocument(); - xmltooling::XercesJanitor docjanitor(dummydoc); - DOMElement* dummy = dummydoc->createElementNS(NULL,path); - - auto_ptr_XMLCh src(config); - dummy->setAttributeNS(NULL,path,src.get()); - - auto_ptr sp(SPConfig::getConfig().ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER,dummy)); - sp->init(); - - pair skew=sp->getUnsignedInt("clockSkew"); - SAMLConfig::getConfig().clock_skew_secs=skew.first ? skew.second : 180; - SPConfig::getConfig().setServiceProvider(sp.release()); - - m_tranLog=new FixedContextCategory(SHIBTRAN_LOGCAT); - m_tranLog->info("opened transaction log"); - m_tranLogLock = xmltooling::Mutex::create(); - } - catch (SAMLException& ex) { - log.fatal("caught exception while loading/initializing configuration: %s",ex.what()); - shutdown(); - return false; - } -#ifndef _DEBUG - catch (...) { - log.fatal("caught exception while loading/initializing configuration"); - shutdown(); - return false; - } -#endif - - log.info("finished loading configuration"); - return true; -} - -void STConfig::shutdown() -{ -#ifdef _DEBUG - xmltooling::NDC ndc("shutdown"); -#endif - Category& log = Category::getInstance(SHIBT_LOGCAT".Config"); - log.info("shutting down the library"); - delete m_tranLogLock; - m_tranLogLock = NULL; - //delete m_tranLog; // This is crashing for some reason, but we're shutting down anyway. - SPConfig::getConfig().term(); - ShibConfig::getConfig().term(); - SAMLConfig::getConfig().term(); - log.info("library shutdown complete"); -} diff --git a/shib-target/shib-handlers.cpp b/shib-target/shib-handlers.cpp deleted file mode 100644 index 8c2583b..0000000 --- a/shib-target/shib-handlers.cpp +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shib-handlers.cpp -- profile handlers that plug into SP - * - * Scott Cantor - * 5/17/2005 - */ - -#include "internal.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -# include -#endif - -using namespace shibsp; -using namespace shibtarget; -using namespace shibboleth; -using namespace saml; -using namespace opensaml::saml2md; -using namespace log4cpp; -using namespace std; - -using opensaml::CommonDomainCookie; -using opensaml::URLEncoder; - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 ) -#endif - -namespace { - class SessionInitiator : public AbstractHandler - { - public: - SessionInitiator(const DOMElement* e) : AbstractHandler(e) {} - ~SessionInitiator() {} - pair run(SPRequest& request, bool isHandler=true) const; - pair ShibAuthnRequest( - SPRequest& request, - const Handler* shire, - const char* dest, - const char* target, - const char* providerId - ) const; - }; - - class SAML1Consumer : public AbstractHandler, public virtual Remoted - { - public: - SAML1Consumer(const DOMElement* e); - ~SAML1Consumer(); - pair run(SPRequest& request, bool isHandler=true) const; - void receive(DDF& in, ostream& out); - private: - string m_address; - static int counter; - }; - - int SAML1Consumer::counter = 0; - - class ShibLogout : public AbstractHandler - { - public: - ShibLogout(const DOMElement* e) : AbstractHandler(e) {} - ~ShibLogout() {} - pair run(SPRequest& request, bool isHandler=true) const; - }; -} - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -Handler* ShibSessionInitiatorFactory(const DOMElement* const & e) -{ - return new SessionInitiator(e); -} - -Handler* SAML1POSTFactory(const DOMElement* const & e) -{ - return new SAML1Consumer(e); -} - -Handler* SAML1ArtifactFactory(const DOMElement* const & e) -{ - return new SAML1Consumer(e); -} - -Handler* ShibLogoutFactory(const DOMElement* const & e) -{ - return new ShibLogout(e); -} - -pair SessionInitiator::run(SPRequest& request, bool isHandler) const -{ - string dupresource; - const char* resource=NULL; - const Handler* ACS=NULL; - const IApplication& app=dynamic_cast(request.getApplication()); - - if (isHandler) { - /* - * Binding is CGI query string with: - * target the resource to direct back to later - * acsIndex optional index of an ACS to use on the way back in - * providerId optional direct invocation of a specific IdP - */ - const char* option=request.getParameter("acsIndex"); - if (option) - ACS=app.getAssertionConsumerServiceByIndex(atoi(option)); - option=request.getParameter("providerId"); - - resource=request.getParameter("target"); - if (!resource || !*resource) { - pair home=app.getString("homeURL"); - if (home.first) - resource=home.second; - else - throw opensaml::FatalProfileException("Session initiator requires a target parameter or a homeURL application property."); - } - else if (!option) { - dupresource=resource; - resource=dupresource.c_str(); - } - - if (option) { - // Here we actually use metadata to invoke the SSO service directly. - // The only currently understood binding is the Shibboleth profile. - - MetadataProvider* m=app.getMetadataProvider(); - xmltooling::Locker locker(m); - const EntityDescriptor* entity=m->getEntityDescriptor(option); - if (!entity) - throw MetadataException("Session initiator unable to locate metadata for provider ($1).", xmltooling::params(1,option)); - const IDPSSODescriptor* role=entity->getIDPSSODescriptor(shibspconstants::SHIB1_PROTOCOL_ENUM); - if (!role) - throw MetadataException( - "Session initiator unable to locate a Shibboleth-aware identity provider role for provider ($1).", - xmltooling::params(1,option) - ); - const EndpointType* ep=EndpointManager(role->getSingleSignOnServices()).getByBinding( - shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI - ); - if (!ep) - throw MetadataException( - "Session initiator unable to locate compatible SSO service for provider ($1).", xmltooling::params(1,option) - ); - auto_ptr_char dest(ep->getLocation()); - return ShibAuthnRequest( - request,ACS ? ACS : app.getDefaultAssertionConsumerService(),dest.get(),resource,app.getString("providerId").second - ); - } - } - else { - // We're running as a "virtual handler" from within the filter. - // The target resource is the current one and everything else is defaulted. - resource=request.getRequestURL(); - } - - if (!ACS) ACS=app.getDefaultAssertionConsumerService(); - - // For now, we only support external session initiation via a wayfURL - pair wayfURL=getString("wayfURL"); - if (!wayfURL.first) - throw ConfigurationException("Session initiator is missing wayfURL property."); - - pair wayfBinding=getXMLString("wayfBinding"); - if (!wayfBinding.first || !XMLString::compareString(wayfBinding.second,shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI)) - // Standard Shib 1.x - return ShibAuthnRequest(request,ACS,wayfURL.second,resource,app.getString("providerId").second); - else if (!strcmp(getString("wayfBinding").second,"urn:mace:shibboleth:1.0:profiles:EAuth")) { - // TODO: Finalize E-Auth profile URI - pair localRelayState=request.getServiceProvider().getPropertySet("InProcess")->getBool("localRelayState"); - if (!localRelayState.first || !localRelayState.second) - throw ConfigurationException("E-Authn requests cannot include relay state, so localRelayState must be enabled."); - - // Here we store the state in a cookie. - pair shib_cookie=app.getCookieNameProps("_shibstate_"); - string stateval = opensaml::SAMLConfig::getConfig().getURLEncoder()->encode(resource) + shib_cookie.second; - request.setCookie(shib_cookie.first.c_str(),stateval.c_str()); - return make_pair(true, request.sendRedirect(wayfURL.second)); - } - - throw opensaml::BindingException("Unsupported WAYF binding ($1).", xmltooling::params(1,getString("wayfBinding").second)); -} - -// Handles Shib 1.x AuthnRequest profile. -pair SessionInitiator::ShibAuthnRequest( - SPRequest& request, - const Handler* shire, - const char* dest, - const char* target, - const char* providerId - ) const -{ - // Compute the ACS URL. We add the ACS location to the base handlerURL. - // Legacy configs will not have the Location property specified, so no suffix will be added. - string ACSloc=request.getHandlerURL(target); - pair loc=shire ? shire->getString("Location") : pair(false,NULL); - if (loc.first) ACSloc+=loc.second; - - URLEncoder* urlenc = opensaml::SAMLConfig::getConfig().getURLEncoder(); - - char timebuf[16]; - sprintf(timebuf,"%u",time(NULL)); - string req=string(dest) + "?shire=" + urlenc->encode(ACSloc.c_str()) + "&time=" + timebuf; - - // How should the resource value be preserved? - pair localRelayState=request.getServiceProvider().getPropertySet("InProcess")->getBool("localRelayState"); - if (!localRelayState.first || !localRelayState.second) { - // The old way, just send it along. - req+="&target=" + urlenc->encode(target); - } - else { - // Here we store the state in a cookie and send a fixed - // value to the IdP so we can recognize it on the way back. - pair shib_cookie=request.getApplication().getCookieNameProps("_shibstate_"); - string stateval = urlenc->encode(target) + shib_cookie.second; - request.setCookie(shib_cookie.first.c_str(),stateval.c_str()); - req+="&target=cookie"; - } - - // Only omitted for 1.1 style requests. - if (providerId) - req+="&providerId=" + urlenc->encode(providerId); - - return make_pair(true, request.sendRedirect(req.c_str())); -} - -SAML1Consumer::SAML1Consumer(const DOMElement* e) : AbstractHandler(e) -{ - m_address += ('A' + (counter++)); - m_address += "::SAML1Consumer::run"; - - // Register for remoted messages. - if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) - SPConfig::getConfig().getServiceProvider()->getListenerService()->regListener(m_address.c_str(),this); -} - -SAML1Consumer::~SAML1Consumer() -{ - ListenerService* listener=SPConfig::getConfig().getServiceProvider()->getListenerService(false); - if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) - listener->unregListener(m_address.c_str(),this); - counter--; -} - -/* - * IPC message definitions: - * - * [A-Z]::SAML1Consumer::run - * - * IN - * application_id - * client_address - * recipient - * SAMLResponse or SAMLart list - * - * OUT - * key - * provider_id - */ -void SAML1Consumer::receive(DDF& in, ostream& sink) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("receive"); -#endif - Category& log=Category::getInstance(SHIBT_LOGCAT".SAML1Consumer"); - - // Find application. - const char* aid=in["application_id"].string(); - const IApplication* app=aid ? dynamic_cast(SPConfig::getConfig().getServiceProvider()->getApplication(aid)) : NULL; - if (!app) { - // Something's horribly wrong. - log.error("couldn't find application (%s) for new session", aid ? aid : "(missing)"); - throw SAMLException("Unable to locate application for new session, deleted?"); - } - - // Check required parameters. - const char* client_address=in["client_address"].string(); - const char* recipient=in["recipient"].string(); - if (!client_address || !recipient) - throw SAMLException("Required parameters missing in call to SAML1Consumer::run"); - - log.debug("processing new assertion for %s", client_address); - log.debug("recipient: %s", recipient); - log.debug("application: %s", app->getId()); - - // Access the application config. - ServiceProvider* conf=SPConfig::getConfig().getServiceProvider(); - xmltooling::Locker confLocker(conf); - - auto_ptr_XMLCh wrecipient(recipient); - - pair checkAddress=pair(false,true); - pair checkReplay=pair(false,true); - const PropertySet* props=app->getPropertySet("Sessions"); - if (props) { - checkAddress=props->getBool("checkAddress"); - if (!checkAddress.first) - checkAddress.second=true; - checkReplay=props->getBool("checkReplay"); - if (!checkReplay.first) - checkReplay.second=true; - } - - // Supports either version... - pair version=getUnsignedInt("MinorVersion","urn:oasis:names:tc:SAML:1.0:protocol"); - if (!version.first) - version.second=1; - - const EntityDescriptor* provider=NULL; - const RoleDescriptor* role=NULL; - MetadataProvider* m=app->getMetadataProvider(); - xmltooling::Locker locker(m); - SAMLBrowserProfile::BrowserProfileResponse bpr; - - try { - const char* samlResponse=in["SAMLResponse"].string(); - if (samlResponse) { - // POST profile - log.debug("executing Browser/POST profile..."); - bpr=app->getBrowserProfile()->receive( - samlResponse, - wrecipient.get(), - NULL, - version.second - ); - } - else { - // Artifact profile - vector SAMLart; - DDF arts=in["SAMLart"]; - DDF art=arts.first(); - while (art.isstring()) { - SAMLart.push_back(art.string()); - art=arts.next(); - } - auto_ptr artifactMapper(app->getArtifactMapper()); - log.debug("executing Browser/Artifact profile..."); - bpr=app->getBrowserProfile()->receive( - SAMLart, - wrecipient.get(), - artifactMapper.get(), - NULL, - version.second - ); - - // Blow it away to clear any locks that might be held. - delete artifactMapper.release(); - } - - // Try and map to metadata (again). - // Once the metadata layer is in the SAML core, the repetition will be fixed. - provider=m->getEntityDescriptor(bpr.assertion->getIssuer()); - if (!provider && bpr.authnStatement->getSubject()->getNameIdentifier() && - bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier()) - provider=m->getEntityDescriptor(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier()); - if (provider) { - role=provider->getIDPSSODescriptor( - version.second==1 ? samlconstants::SAML11_PROTOCOL_ENUM : samlconstants::SAML10_PROTOCOL_ENUM - ); - } - - // This isn't likely, since the profile must have found a role. - if (!role) { - MetadataException ex("Unable to locate role-specific metadata for identity provider."); - annotateException(&ex,provider); // throws it - } - - // Maybe verify the client address.... - if (checkAddress.second) { - log.debug("verifying client address"); - // Verify the client address exists - const XMLCh* wip = bpr.authnStatement->getSubjectIP(); - if (wip && *wip) { - // Verify the client address matches authentication - auto_ptr_char this_ip(wip); - if (strcmp(client_address, this_ip.get())) { - opensaml::FatalProfileException ex( - "Your client's current address ($1) differs from the one used when you authenticated " - "to your identity provider. To correct this problem, you may need to bypass a proxy server. " - "Please contact your local support staff or help desk for assistance.", - xmltooling::params(1,client_address) - ); - annotateException(&ex,role); // throws it - } - } - } - } - catch (exception&) { - bpr.clear(); - throw; - } - catch (...) { - log.error("caught unknown exception"); - bpr.clear(); -#ifdef _DEBUG - throw; -#else - SAMLException e("An unexpected error occurred while creating your session."); - shibboleth::annotateException(&e,role); -#endif - } - - // It passes all our tests -- create a new session. - log.info("creating new session"); - - // Insert into cache. - auto_ptr_char authContext(bpr.authnStatement->getAuthMethod()); - string key=dynamic_cast(conf->getSessionCache())->insert( - app, - role, - client_address, - bpr.authnStatement->getSubject(), - authContext.get(), - bpr.response - ); - // objects owned by cache now - log.debug("new session id: %s", key.c_str()); - auto_ptr_char oname(provider->getEntityID()); - DDF out=DDF(NULL).structure(); - out.addmember("key").string(key.c_str()); - out.addmember("provider_id").string(oname.get()); - - sink << out; -} - -pair SAML1Consumer::run(SPRequest& request, bool isHandler) const -{ - DDF in,out; - DDFJanitor jin(in),jout(out); - - pair binding=getXMLString("Binding"); - if (!binding.first || !XMLString::compareString(binding.second,SAMLBrowserProfile::BROWSER_POST)) { -#ifdef HAVE_STRCASECMP - if (strcasecmp(request.getMethod(), "POST")) { -#else - if (_stricmp(request.getMethod(), "POST")) { -#endif - request.log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring non-POST request"); - return pair(false,NULL); - } -#ifdef HAVE_STRCASECMP - if (strcasecmp(request.getContentType().c_str(),"application/x-www-form-urlencoded")) { -#else - if (_stricmp(request.getContentType().c_str(),"application/x-www-form-urlencoded")) { -#endif - request.log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring submission with unknown content-type."); - return pair(false,0); - } - - const char* samlResponse = request.getParameter("SAMLResponse"); - if (!samlResponse) { - request.log(SPRequest::SPInfo, "SAML 1.x Browser/POST handler ignoring request with no SAMLResponse parameter."); - return pair(false,0); - } - - in=DDF(m_address.c_str()).structure(); - in.addmember("SAMLResponse").string(samlResponse); - } - else if (!XMLString::compareString(binding.second,SAMLBrowserProfile::BROWSER_ARTIFACT)) { -#ifdef HAVE_STRCASECMP - if (strcasecmp(request.getMethod(), "GET")) { -#else - if (_stricmp(request.getMethod(), "GET")) { -#endif - request.log(SPRequest::SPInfo, "SAML 1.x Browser/Artifact handler ignoring non-GET request"); - return pair(false,0); - } - - vector arts; - if (request.getParameters("SAMLart",arts)==0) { - request.log(SPRequest::SPInfo, "SAML 1.x Browser/Artifact handler ignoring request with no SAMLart parameter."); - return pair(false,0); - } - - in=DDF(m_address.c_str()).structure(); - DDF artlist=in.addmember("SAMLart").list(); - - for (vector::const_iterator a=arts.begin(); a!=arts.end(); ++a) - artlist.add(DDF(NULL).string(*a)); - } - - // Compute the endpoint location. - string hURL=request.getHandlerURL(request.getRequestURL()); - pair loc=getString("Location"); - string recipient=loc.first ? hURL + loc.second : hURL; - in.addmember("recipient").string(recipient.c_str()); - - // Add remaining parameters. - in.addmember("application_id").string(request.getApplication().getId()); - in.addmember("client_address").string(request.getRemoteAddr().c_str()); - - out=request.getServiceProvider().getListenerService()->send(in); - if (!out["key"].isstring()) - throw opensaml::FatalProfileException("Remote processing of SAML 1.x Browser profile did not return a usable session key."); - string key=out["key"].string(); - - request.log(SPRequest::SPDebug, string("profile processing succeeded, new session created (") + key + ")"); - - const char* target=request.getParameter("TARGET"); - if (target && !strcmp(target,"default")) { - pair homeURL=request.getApplication().getString("homeURL"); - target=homeURL.first ? homeURL.second : "/"; - } - else if (!target || !strcmp(target,"cookie")) { - // Pull the target value from the "relay state" cookie. - pair relay_cookie = request.getApplication().getCookieNameProps("_shibstate_"); - const char* relay_state = request.getCookie(relay_cookie.first.c_str()); - if (!relay_state || !*relay_state) { - // No apparent relay state value to use, so fall back on the default. - pair homeURL=request.getApplication().getString("homeURL"); - target=homeURL.first ? homeURL.second : "/"; - } - else { - char* rscopy=strdup(relay_state); - opensaml::SAMLConfig::getConfig().getURLEncoder()->decode(rscopy); - hURL=rscopy; - free(rscopy); - target=hURL.c_str(); - } - request.setCookie(relay_cookie.first.c_str(),relay_cookie.second); - } - - // We've got a good session, set the session cookie. - pair shib_cookie=request.getApplication().getCookieNameProps("_shibsession_"); - key += shib_cookie.second; - request.setCookie(shib_cookie.first.c_str(), key.c_str()); - - const char* providerId=out["provider_id"].string(); - if (providerId) { - const PropertySet* sessionProps=request.getApplication().getPropertySet("Sessions"); - pair idpHistory=sessionProps->getBool("idpHistory"); - if (!idpHistory.first || idpHistory.second) { - // Set an IdP history cookie locally (essentially just a CDC). - CommonDomainCookie cdc(request.getCookie(CommonDomainCookie::CDCName)); - - // Either leave in memory or set an expiration. - pair days=sessionProps->getUnsignedInt("idpHistoryDays"); - if (!days.first || days.second==0) { - key = string(cdc.set(providerId)) + shib_cookie.second; - request.setCookie(CommonDomainCookie::CDCName, key.c_str()); - } - else { - time_t now=time(NULL) + (days.second * 24 * 60 * 60); -#ifdef HAVE_GMTIME_R - struct tm res; - struct tm* ptime=gmtime_r(&now,&res); -#else - struct tm* ptime=gmtime(&now); -#endif - char timebuf[64]; - strftime(timebuf,64,"%a, %d %b %Y %H:%M:%S GMT",ptime); - key = string(cdc.set(providerId)) + shib_cookie.second + "; expires=" + timebuf; - request.setCookie(CommonDomainCookie::CDCName, key.c_str()); - } - } - } - - // Now redirect to the target. - return make_pair(true, request.sendRedirect(target)); -} - -pair ShibLogout::run(SPRequest& request, bool isHandler) const -{ - // Recover the session key. - pair shib_cookie = request.getApplication().getCookieNameProps("_shibsession_"); - const char* session_id = request.getCookie(shib_cookie.first.c_str()); - - // Logout is best effort. - if (session_id && *session_id) { - try { - // TODO: port to new cache API - //request.getServiceProvider().getSessionCache()->remove(session_id,request.getApplication(),request.getRemoteAddr().c_str()); - } - catch (exception& e) { - request.log(SPRequest::SPError, string("logout processing failed with exception: ") + e.what()); - } -#ifndef _DEBUG - catch (...) { - request.log(SPRequest::SPError, "logout processing failed with unknown exception"); - } -#endif - // We send the cookie property alone, which acts as an empty value. - request.setCookie(shib_cookie.first.c_str(),shib_cookie.second); - } - - const char* ret=request.getParameter("return"); - if (!ret) - ret=getString("ResponseLocation").second; - if (!ret) - ret=request.getApplication().getString("homeURL").second; - if (!ret) - ret="/"; - return make_pair(true, request.sendRedirect(ret)); -} diff --git a/shib-target/shib-ini.cpp b/shib-target/shib-ini.cpp deleted file mode 100644 index edf5908..0000000 --- a/shib-target/shib-ini.cpp +++ /dev/null @@ -1,1159 +0,0 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shib-ini.h -- config file handling, now XML-based - * - * $Id$ - */ - -#include "internal.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace shibsp; -using namespace shibtarget; -using namespace shibboleth; -using namespace saml; -using namespace opensaml::saml1; -using namespace opensaml::saml2md; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; -using xmlsignature::CredentialResolver; - -namespace { - - vector g_noHandlers; - - // Application configuration wrapper - class XMLApplication : public virtual IApplication, public DOMPropertySet, public DOMNodeFilter - { - public: - XMLApplication(const ServiceProvider*, const DOMElement* e, const XMLApplication* base=NULL); - ~XMLApplication() { cleanup(); } - - // PropertySet - pair getBool(const char* name, const char* ns=NULL) const; - pair getString(const char* name, const char* ns=NULL) const; - pair getXMLString(const char* name, const char* ns=NULL) const; - pair getUnsignedInt(const char* name, const char* ns=NULL) const; - pair getInt(const char* name, const char* ns=NULL) const; - const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const; - - // IApplication - const char* getId() const {return getString("id").second;} - const char* getHash() const {return m_hash.c_str();} - MetadataProvider* getMetadataProvider() const; - TrustEngine* getTrustEngine() const; - const vector& getAudiences() const; - const PropertySet* getCredentialUse(const EntityDescriptor* provider) const; - - const SAMLBrowserProfile* getBrowserProfile() const {return m_profile;} - const SAMLBinding* getBinding(const XMLCh* binding) const - {return XMLString::compareString(SAMLBinding::SOAP,binding) ? NULL : m_binding;} - SAMLBrowserProfile::ArtifactMapper* getArtifactMapper() const {return new STArtifactMapper(this);} - void validateToken( - SAMLAssertion* token, - time_t t=0, - const RoleDescriptor* role=NULL, - const TrustEngine* trust=NULL - ) const; - const Handler* getDefaultSessionInitiator() const; - const Handler* getSessionInitiatorById(const char* id) const; - const Handler* getDefaultAssertionConsumerService() const; - const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const; - const vector& getAssertionConsumerServicesByBinding(const XMLCh* binding) const; - const Handler* getHandler(const char* path) const; - - // Provides filter to exclude special config elements. - short acceptNode(const DOMNode* node) const; - - private: - void cleanup(); - const ServiceProvider* m_sp; // this is ok because its locking scope includes us - const XMLApplication* m_base; - string m_hash; - MetadataProvider* m_metadata; - TrustEngine* m_trust; - vector m_audiences; - ShibBrowserProfile* m_profile; - SAMLBinding* m_binding; - ShibHTTPHook* m_bindingHook; - - // manage handler objects - vector m_handlers; - - // maps location (path info) to applicable handlers - map m_handlerMap; - - // maps unique indexes to consumer services - map m_acsIndexMap; - - // pointer to default consumer service - const Handler* m_acsDefault; - - // maps binding strings to supporting consumer service(s) -#ifdef HAVE_GOOD_STL - typedef map > ACSBindingMap; -#else - typedef map > ACSBindingMap; -#endif - ACSBindingMap m_acsBindingMap; - - // maps unique ID strings to session initiators - map m_sessionInitMap; - - // pointer to default session initiator - const Handler* m_sessionInitDefault; - - DOMPropertySet* m_credDefault; -#ifdef HAVE_GOOD_STL - map m_credMap; -#else - map m_credMap; -#endif - }; - - // Top-level configuration implementation - class XMLConfig; - class XMLConfigImpl : public DOMPropertySet, public DOMNodeFilter - { - public: - XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer); - ~XMLConfigImpl(); - - RequestMapper* m_requestMapper; - map m_appmap; - map m_credResolverMap; - vector m_attrFactories; - - // Provides filter to exclude special config elements. - short acceptNode(const DOMNode* node) const; - - void setDocument(DOMDocument* doc) { - m_document = doc; - } - - private: - void doExtensions(const DOMElement* e, const char* label, Category& log); - - const XMLConfig* m_outer; - DOMDocument* m_document; - }; - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 ) -#endif - - class XMLConfig : public ServiceProvider, public ReloadableXMLFile - { - public: - XMLConfig(const DOMElement* e) - : ReloadableXMLFile(e), m_impl(NULL), m_listener(NULL), m_sessionCache(NULL) { - } - - void init() { - load(); - } - - ~XMLConfig() { - delete m_impl; - delete m_sessionCache; - delete m_listener; - delete m_tranLog; - XMLToolingConfig::getConfig().setReplayCache(NULL); - for_each(m_storage.begin(), m_storage.end(), xmltooling::cleanup_pair()); - } - - // PropertySet - pair getBool(const char* name, const char* ns=NULL) const {return m_impl->getBool(name,ns);} - pair getString(const char* name, const char* ns=NULL) const {return m_impl->getString(name,ns);} - pair getXMLString(const char* name, const char* ns=NULL) const {return m_impl->getXMLString(name,ns);} - pair getUnsignedInt(const char* name, const char* ns=NULL) const {return m_impl->getUnsignedInt(name,ns);} - pair getInt(const char* name, const char* ns=NULL) const {return m_impl->getInt(name,ns);} - const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const {return m_impl->getPropertySet(name,ns);} - const DOMElement* getElement() const {return m_impl->getElement();} - - // ServiceProvider - TransactionLog* getTransactionLog() const { - if (m_tranLog) - return m_tranLog; - throw ConfigurationException("No TransactionLog available."); - } - - StorageService* getStorageService(const char* id) const { - if (id) { - map::const_iterator i=m_storage.find(id); - if (i!=m_storage.end()) - return i->second; - } - return NULL; - } - - ListenerService* getListenerService(bool required=true) const { - if (required && !m_listener) - throw ConfigurationException("No ListenerService available."); - return m_listener; - } - - SessionCache* getSessionCache(bool required=true) const { - if (required && !m_sessionCache) - throw ConfigurationException("No SessionCache available."); - return m_sessionCache; - } - - RequestMapper* getRequestMapper(bool required=true) const { - if (required && !m_impl->m_requestMapper) - throw ConfigurationException("No RequestMapper available."); - return m_impl->m_requestMapper; - } - - const Application* getApplication(const char* applicationId) const { - map::const_iterator i=m_impl->m_appmap.find(applicationId); - return (i!=m_impl->m_appmap.end()) ? i->second : NULL; - } - - CredentialResolver* getCredentialResolver(const char* id) const { - if (id) { - map::const_iterator i=m_impl->m_credResolverMap.find(id); - if (i!=m_impl->m_credResolverMap.end()) - return i->second; - } - return NULL; - } - - protected: - pair load(); - - private: - friend class XMLConfigImpl; - XMLConfigImpl* m_impl; - mutable ListenerService* m_listener; - mutable SessionCache* m_sessionCache; - mutable TransactionLog* m_tranLog; - mutable map m_storage; - }; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - - static const XMLCh AAPProvider[] = UNICODE_LITERAL_11(A,A,P,P,r,o,v,i,d,e,r); - static const XMLCh _Application[] = UNICODE_LITERAL_11(A,p,p,l,i,c,a,t,i,o,n); - static const XMLCh Applications[] = UNICODE_LITERAL_12(A,p,p,l,i,c,a,t,i,o,n,s); - static const XMLCh AttributeFactory[] = UNICODE_LITERAL_16(A,t,t,r,i,b,u,t,e,F,a,c,t,o,r,y); - static const XMLCh Credentials[] = UNICODE_LITERAL_11(C,r,e,d,e,n,t,i,a,l,s); - static const XMLCh CredentialsProvider[] = UNICODE_LITERAL_19(C,r,e,d,e,n,t,i,a,l,s,P,r,o,v,i,d,e,r); - static const XMLCh CredentialUse[] = UNICODE_LITERAL_13(C,r,e,d,e,n,t,i,a,l,U,s,e); - static const XMLCh DiagnosticService[] = UNICODE_LITERAL_17(D,i,a,g,n,o,s,t,i,c,S,e,r,v,i,c,e); - static const XMLCh fatal[] = UNICODE_LITERAL_5(f,a,t,a,l); - static const XMLCh FileResolver[] = UNICODE_LITERAL_12(F,i,l,e,R,e,s,o,l,v,e,r); - static const XMLCh Global[] = UNICODE_LITERAL_6(G,l,o,b,a,l); - static const XMLCh Id[] = UNICODE_LITERAL_2(I,d); - static const XMLCh Implementation[] = UNICODE_LITERAL_14(I,m,p,l,e,m,e,n,t,a,t,i,o,n); - static const XMLCh InProcess[] = UNICODE_LITERAL_9(I,n,P,r,o,c,e,s,s); - static const XMLCh Library[] = UNICODE_LITERAL_7(L,i,b,r,a,r,y); - static const XMLCh Listener[] = UNICODE_LITERAL_8(L,i,s,t,e,n,e,r); - static const XMLCh Local[] = UNICODE_LITERAL_5(L,o,c,a,l); - static const XMLCh logger[] = UNICODE_LITERAL_6(l,o,g,g,e,r); - static const XMLCh MemoryListener[] = UNICODE_LITERAL_14(M,e,m,o,r,y,L,i,s,t,e,n,e,r); - static const XMLCh MemorySessionCache[] = UNICODE_LITERAL_18(M,e,m,o,r,y,S,e,s,s,i,o,n,C,a,c,h,e); - static const XMLCh RelyingParty[] = UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y); - static const XMLCh _ReplayCache[] = UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e); - static const XMLCh RequestMapProvider[] = UNICODE_LITERAL_18(R,e,q,u,e,s,t,M,a,p,P,r,o,v,i,d,e,r); - static const XMLCh _SessionCache[] = UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e); - static const XMLCh SessionInitiator[] = UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r); - static const XMLCh _StorageService[] = UNICODE_LITERAL_14(S,t,o,r,a,g,e,S,e,r,v,i,c,e); - static const XMLCh OutOfProcess[] = UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s); - static const XMLCh TCPListener[] = UNICODE_LITERAL_11(T,C,P,L,i,s,t,e,n,e,r); - static const XMLCh TrustProvider[] = UNICODE_LITERAL_13(T,r,u,s,t,P,r,o,v,i,d,e,r); - static const XMLCh UnixListener[] = UNICODE_LITERAL_12(U,n,i,x,L,i,s,t,e,n,e,r); - static const XMLCh _MetadataProvider[] = UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r); - static const XMLCh _path[] = UNICODE_LITERAL_4(p,a,t,h); - static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e); - -} - -ServiceProvider* shibtarget::XMLServiceProviderFactory(const DOMElement* const & e) -{ - return new XMLConfig(e); -} - -XMLApplication::XMLApplication( - const ServiceProvider* sp, - const DOMElement* e, - const XMLApplication* base - ) : m_sp(sp), m_base(base), m_metadata(NULL), m_trust(NULL), m_profile(NULL), m_binding(NULL), m_bindingHook(NULL), - m_credDefault(NULL), m_sessionInitDefault(NULL), m_acsDefault(NULL) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("XMLApplication"); -#endif - Category& log=Category::getInstance(SHIBT_LOGCAT".Application"); - - try { - // First load any property sets. - map root_remap; - root_remap["shire"]="session"; - root_remap["shireURL"]="handlerURL"; - root_remap["shireSSL"]="handlerSSL"; - load(e,log,this,&root_remap); - - const PropertySet* propcheck=getPropertySet("Errors"); - if (propcheck && !propcheck->getString("session").first) - throw ConfigurationException(" element requires 'session' (or deprecated 'shire') attribute"); - propcheck=getPropertySet("Sessions"); - if (propcheck && !propcheck->getString("handlerURL").first) - throw ConfigurationException(" element requires 'handlerURL' (or deprecated 'shireURL') attribute"); - - SPConfig& conf=SPConfig::getConfig(); - XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig(); - opensaml::SAMLConfig& samlConf=opensaml::SAMLConfig::getConfig(); - SAMLConfig& shibConf=SAMLConfig::getConfig(); - - m_hash=getId(); - m_hash+=getString("providerId").second; - m_hash=samlConf.hashSHA1(m_hash.c_str(), true); - - // Process handlers. - Handler* handler=NULL; - bool hardACS=false, hardSessionInit=false; - const DOMElement* child = XMLHelper::getFirstChildElement(propcheck->getElement()); - while (child) { - xmltooling::auto_ptr_char bindprop(child->getAttributeNS(NULL,EndpointType::BINDING_ATTRIB_NAME)); - if (!bindprop.get() || !*(bindprop.get())) { - log.warn("md:AssertionConsumerService element has no Binding attribute, skipping it..."); - child = XMLHelper::getNextSiblingElement(child); - continue; - } - - try { - // A handler is based on the Binding property in conjunction with the element name. - // If it's an ACS or SI, also handle index/id mappings and defaulting. - if (XMLHelper::isNodeNamed(child,samlconstants::SAML20MD_NS,AssertionConsumerService::LOCAL_NAME)) { - handler=conf.AssertionConsumerServiceManager.newPlugin(bindprop.get(),child); - // Map by binding (may be > 1 per binding, e.g. SAML 1.0 vs 1.1) -#ifdef HAVE_GOOD_STL - m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler); -#else - m_acsBindingMap[handler->getString("Binding").second].push_back(handler); -#endif - m_acsIndexMap[handler->getUnsignedInt("index").second]=handler; - - if (!hardACS) { - pair defprop=handler->getBool("isDefault"); - if (defprop.first) { - if (defprop.second) { - hardACS=true; - m_acsDefault=handler; - } - } - else if (!m_acsDefault) - m_acsDefault=handler; - } - } - else if (XMLString::equals(child->getLocalName(),SessionInitiator)) { - handler=conf.SessionInitiatorManager.newPlugin(bindprop.get(),child); - pair si_id=handler->getString("id"); - if (si_id.first && si_id.second) - m_sessionInitMap[si_id.second]=handler; - if (!hardSessionInit) { - pair defprop=handler->getBool("isDefault"); - if (defprop.first) { - if (defprop.second) { - hardSessionInit=true; - m_sessionInitDefault=handler; - } - } - else if (!m_sessionInitDefault) - m_sessionInitDefault=handler; - } - } - else if (XMLHelper::isNodeNamed(child,samlconstants::SAML20MD_NS,SingleLogoutService::LOCAL_NAME)) { - handler=conf.SingleLogoutServiceManager.newPlugin(bindprop.get(),child); - } - else if (XMLHelper::isNodeNamed(child,samlconstants::SAML20MD_NS,ManageNameIDService::LOCAL_NAME)) { - handler=conf.ManageNameIDServiceManager.newPlugin(bindprop.get(),child); - } - else { - handler=conf.HandlerManager.newPlugin(bindprop.get(),child); - } - } - catch (exception& ex) { - log.error("caught exception processing md:AssertionConsumerService element: %s",ex.what()); - } - - // Save off the objects after giving the property set to the handler for its use. - m_handlers.push_back(handler); - - // Insert into location map. - pair location=handler->getString("Location"); - if (location.first && *location.second == '/') - m_handlerMap[location.second]=handler; - else if (location.first) - m_handlerMap[string("/") + location.second]=handler; - - child = XMLHelper::getNextSiblingElement(child); - } - - // If no handlers defined at the root, assume a legacy configuration. - if (!m_base && m_handlers.empty()) { - // A legacy config installs a SAML POST handler at the root handler location. - // We use the Sessions element itself as the PropertySet. - Handler* h1=conf.SessionInitiatorManager.newPlugin( - shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI,propcheck->getElement() - ); - m_handlers.push_back(h1); - m_sessionInitDefault=h1; - - Handler* h2=conf.AssertionConsumerServiceManager.newPlugin( - samlconstants::SAML1_PROFILE_BROWSER_POST,propcheck->getElement() - ); - m_handlers.push_back(h2); - m_handlerMap[""] = h2; - m_acsDefault=h2; - } - - DOMNodeList* nlist=e->getElementsByTagNameNS(samlconstants::SAML1_NS,Audience::LOCAL_NAME); - for (XMLSize_t i=0; nlist && igetLength(); i++) - if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes()) - m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue()); - - // Always include our own providerId as an audience. - m_audiences.push_back(getXMLString("providerId").second); - - if (conf.isEnabled(SPConfig::AttributeResolver)) { - child = XMLHelper::getFirstChildElement(e,AAPProvider); - while (child) { - // TODO: some kind of compatibility - child = XMLHelper::getNextSiblingElement(child,AAPProvider); - } - } - - if (conf.isEnabled(SPConfig::Metadata)) { - vector os2providers; - child = XMLHelper::getFirstChildElement(e,_MetadataProvider); - while (child) { - xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type)); - log.info("building metadata provider of type %s...",type.get()); - try { - auto_ptr mp(samlConf.MetadataProviderManager.newPlugin(type.get(),child)); - mp->init(); - os2providers.push_back(mp.release()); - } - catch (exception& ex) { - log.crit("error building/initializing metadata provider: %s", ex.what()); - } - - child = XMLHelper::getNextSiblingElement(child,_MetadataProvider); - } - - if (os2providers.size()==1) - m_metadata=os2providers.front(); - else if (os2providers.size()>1) { - try { - m_metadata = samlConf.MetadataProviderManager.newPlugin(CHAINING_METADATA_PROVIDER,NULL); - ChainingMetadataProvider* chainMeta = dynamic_cast(m_metadata); - while (!os2providers.empty()) { - chainMeta->addMetadataProvider(os2providers.back()); - os2providers.pop_back(); - } - } - catch (exception& ex) { - log.crit("error building chaining metadata provider wrapper: %s",ex.what()); - for_each(os2providers.begin(), os2providers.end(), xmltooling::cleanup()); - } - } - } - - if (conf.isEnabled(SPConfig::Trust)) { - ChainingTrustEngine* chainTrust = NULL; - child = XMLHelper::getFirstChildElement(e,TrustProvider); - while (child) { - xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type)); - log.info("building trust provider of type %s...",type.get()); - try { - if (!m_trust) { - // For compatibility with old engine types, we're assuming a Shib engine is likely, - // which requires chaining, so we'll build that regardless. - m_trust = xmlConf.TrustEngineManager.newPlugin(CHAINING_TRUSTENGINE,NULL); - chainTrust = dynamic_cast(m_trust); - } - if (!strcmp(type.get(),"edu.internet2.middleware.shibboleth.common.provider.ShibbolethTrust")) { - chainTrust->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(EXPLICIT_KEY_TRUSTENGINE,child)); - chainTrust->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(SHIBBOLETH_PKIX_TRUSTENGINE,child)); - } - else if (!strcmp(type.get(),"edu.internet2.middleware.shibboleth.common.provider.BasicTrust")) { - chainTrust->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(EXPLICIT_KEY_TRUSTENGINE,child)); - } - else { - chainTrust->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(type.get(),child)); - } - } - catch (exception& ex) { - log.crit("error building trust provider: %s",ex.what()); - } - - child = XMLHelper::getNextSiblingElement(child,TrustProvider); - } - } - - // Finally, load credential mappings. - child = XMLHelper::getFirstChildElement(e,CredentialUse); - if (child) { - m_credDefault=new DOMPropertySet(); - m_credDefault->load(child,log,this); - child = XMLHelper::getFirstChildElement(child,RelyingParty); - while (child) { - DOMPropertySet* rp=new DOMPropertySet(); - rp->load(child,log,this); - m_credMap[child->getAttributeNS(NULL,opensaml::saml2::Attribute::NAME_ATTRIB_NAME)]=rp; - child = XMLHelper::getNextSiblingElement(child,RelyingParty); - } - } - - if (conf.isEnabled(SPConfig::OutOfProcess)) { - // Really finally, build local browser profile and binding objects. - m_profile=new ShibBrowserProfile(this, getMetadataProvider(), getTrustEngine()); - m_bindingHook=new ShibHTTPHook(getTrustEngine()); - m_binding=SAMLBinding::getInstance(SAMLBinding::SOAP); - SAMLSOAPHTTPBinding* bptr=dynamic_cast(m_binding); - if (!bptr) { - log.fatal("binding implementation was not SOAP over HTTP"); - throw UnknownExtensionException("binding implementation was not SOAP over HTTP"); - } - bptr->addHook(m_bindingHook,m_bindingHook); // the hook is its own global context - } - } - catch (exception&) { - cleanup(); - throw; - } -#ifndef _DEBUG - catch (...) { - cleanup(); - throw; - } -#endif -} - -void XMLApplication::cleanup() -{ - delete m_bindingHook; - delete m_binding; - delete m_profile; - for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup()); - - delete m_credDefault; -#ifdef HAVE_GOOD_STL - for_each(m_credMap.begin(),m_credMap.end(),xmltooling::cleanup_pair()); -#else - for_each(m_credMap.begin(),m_credMap.end(),xmltooling::cleanup_pair()); -#endif - - delete m_trust; - delete m_metadata; -} - -short XMLApplication::acceptNode(const DOMNode* node) const -{ - if (XMLHelper::isNodeNamed(node,samlconstants::SAML1_NS,AttributeDesignator::LOCAL_NAME)) - return FILTER_REJECT; - else if (XMLHelper::isNodeNamed(node,samlconstants::SAML20_NS,opensaml::saml1::Attribute::LOCAL_NAME)) - return FILTER_REJECT; - else if (XMLHelper::isNodeNamed(node,samlconstants::SAML1_NS,Audience::LOCAL_NAME)) - return FILTER_REJECT; - const XMLCh* name=node->getLocalName(); - if (XMLString::equals(name,_Application) || - XMLString::equals(name,AssertionConsumerService::LOCAL_NAME) || - XMLString::equals(name,SingleLogoutService::LOCAL_NAME) || - XMLString::equals(name,DiagnosticService) || - XMLString::equals(name,SessionInitiator) || - XMLString::equals(name,AAPProvider) || - XMLString::equals(name,CredentialUse) || - XMLString::equals(name,RelyingParty) || - XMLString::equals(name,_MetadataProvider) || - XMLString::equals(name,TrustProvider)) - return FILTER_REJECT; - - return FILTER_ACCEPT; -} - -pair XMLApplication::getBool(const char* name, const char* ns) const -{ - pair ret=DOMPropertySet::getBool(name,ns); - if (ret.first) - return ret; - return m_base ? m_base->getBool(name,ns) : ret; -} - -pair XMLApplication::getString(const char* name, const char* ns) const -{ - pair ret=DOMPropertySet::getString(name,ns); - if (ret.first) - return ret; - return m_base ? m_base->getString(name,ns) : ret; -} - -pair XMLApplication::getXMLString(const char* name, const char* ns) const -{ - pair ret=DOMPropertySet::getXMLString(name,ns); - if (ret.first) - return ret; - return m_base ? m_base->getXMLString(name,ns) : ret; -} - -pair XMLApplication::getUnsignedInt(const char* name, const char* ns) const -{ - pair ret=DOMPropertySet::getUnsignedInt(name,ns); - if (ret.first) - return ret; - return m_base ? m_base->getUnsignedInt(name,ns) : ret; -} - -pair XMLApplication::getInt(const char* name, const char* ns) const -{ - pair ret=DOMPropertySet::getInt(name,ns); - if (ret.first) - return ret; - return m_base ? m_base->getInt(name,ns) : ret; -} - -const PropertySet* XMLApplication::getPropertySet(const char* name, const char* ns) const -{ - const PropertySet* ret=DOMPropertySet::getPropertySet(name,ns); - if (ret || !m_base) - return ret; - return m_base->getPropertySet(name,ns); -} - -MetadataProvider* XMLApplication::getMetadataProvider() const -{ - return (!m_metadata && m_base) ? m_base->getMetadataProvider() : m_metadata; -} - -TrustEngine* XMLApplication::getTrustEngine() const -{ - return (!m_trust && m_base) ? m_base->getTrustEngine() : m_trust; -} - -const vector& XMLApplication::getAudiences() const -{ - return (m_audiences.empty() && m_base) ? m_base->getAudiences() : m_audiences; -} - -const PropertySet* XMLApplication::getCredentialUse(const EntityDescriptor* provider) const -{ - if (!m_credDefault && m_base) - return m_base->getCredentialUse(provider); - -#ifdef HAVE_GOOD_STL - map::const_iterator i=m_credMap.find(provider->getEntityID()); - if (i!=m_credMap.end()) - return i->second; - const EntitiesDescriptor* group=dynamic_cast(provider->getParent()); - while (group) { - if (group->getName()) { - i=m_credMap.find(group->getName()); - if (i!=m_credMap.end()) - return i->second; - } - group=dynamic_cast(group->getParent()); - } -#else - map::const_iterator i=m_credMap.begin(); - for (; i!=m_credMap.end(); i++) { - if (XMLString::equals(i->first,provider->getId())) - return i->second; - const EntitiesDescriptor* group=dynamic_cast(provider->getParent()); - while (group) { - if (XMLString::equals(i->first,group->getName())) - return i->second; - group=dynamic_cast(group->getParent()); - } - } -#endif - return m_credDefault; -} - -void XMLApplication::validateToken(SAMLAssertion* token, time_t ts, const RoleDescriptor* role, const TrustEngine* trust) const -{ -#ifdef _DEBUG - xmltooling::NDC ndc("validateToken"); -#endif - Category& log=Category::getInstance(SHIBT_LOGCAT".Application"); - - // First we verify the time conditions, using the specified timestamp, if non-zero. - SAMLConfig& config=SAMLConfig::getConfig(); - if (ts>0) { - const SAMLDateTime* notBefore=token->getNotBefore(); - if (notBefore && ts+config.clock_skew_secs < notBefore->getEpoch()) - throw opensaml::FatalProfileException("Assertion is not yet valid."); - const SAMLDateTime* notOnOrAfter=token->getNotOnOrAfter(); - if (notOnOrAfter && notOnOrAfter->getEpoch() <= ts-config.clock_skew_secs) - throw opensaml::FatalProfileException("Assertion is no longer valid."); - } - - // Now we process conditions. Only audience restrictions at the moment. - Iterator conditions=token->getConditions(); - while (conditions.hasNext()) { - SAMLCondition* cond=conditions.next(); - const SAMLAudienceRestrictionCondition* ac=dynamic_cast(cond); - if (!ac) { - ostringstream os; - os << *cond; - log.error("unrecognized Condition in assertion (%s)",os.str().c_str()); - throw xmltooling::UnknownExtensionException("Assertion contains an unrecognized condition."); - } - else if (!ac->eval(getAudiences())) { - ostringstream os; - os << *ac; - log.error("unacceptable AudienceRestrictionCondition in assertion (%s)",os.str().c_str()); - throw opensaml::FatalProfileException("Assertion contains an unacceptable AudienceRestrictionCondition."); - } - } - - if (!role || !trust) { - log.warn("no metadata provided, so no signature validation was performed"); - return; - } - - const PropertySet* credUse=getCredentialUse(dynamic_cast(role->getParent())); - pair signedAssertions=credUse ? credUse->getBool("signedAssertions") : make_pair(false,false); - - if (token->isSigned()) { - - // This will all change, but for fun, we'll port the object from OS1->OS2 for validation. - stringstream s; - s << *token; - DOMDocument* doc = XMLToolingConfig::getConfig().getValidatingParser().parse(s); - XercesJanitor jdoc(doc); - auto_ptr os2ass(AssertionBuilder::buildAssertion()); - os2ass->unmarshall(doc->getDocumentElement(),true); - jdoc.release(); - - if (!trust->validate(*(os2ass->getSignature()),*role)) - throw xmltooling::XMLSecurityException("Assertion signature did not validate."); - } - else if (signedAssertions.first && signedAssertions.second) - throw xmltooling::XMLSecurityException("Assertion was unsigned, violating policy based on the issuer."); -} - -const Handler* XMLApplication::getDefaultSessionInitiator() const -{ - if (m_sessionInitDefault) return m_sessionInitDefault; - return m_base ? m_base->getDefaultSessionInitiator() : NULL; -} - -const Handler* XMLApplication::getSessionInitiatorById(const char* id) const -{ - map::const_iterator i=m_sessionInitMap.find(id); - if (i!=m_sessionInitMap.end()) return i->second; - return m_base ? m_base->getSessionInitiatorById(id) : NULL; -} - -const Handler* XMLApplication::getDefaultAssertionConsumerService() const -{ - if (m_acsDefault) return m_acsDefault; - return m_base ? m_base->getDefaultAssertionConsumerService() : NULL; -} - -const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const -{ - map::const_iterator i=m_acsIndexMap.find(index); - if (i!=m_acsIndexMap.end()) return i->second; - return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : NULL; -} - -const vector& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const -{ -#ifdef HAVE_GOOD_STL - ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding); -#else - xmltooling::auto_ptr_char temp(binding); - ACSBindingMap::const_iterator i=m_acsBindingMap.find(temp.get()); -#endif - if (i!=m_acsBindingMap.end()) - return i->second; - return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers; -} - -const Handler* XMLApplication::getHandler(const char* path) const -{ - string wrap(path); - map::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?'))); - if (i!=m_handlerMap.end()) - return i->second; - return m_base ? m_base->getHandler(path) : NULL; -} - -short XMLConfigImpl::acceptNode(const DOMNode* node) const -{ - if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB1SPCONFIG_NS) && - !XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB2SPCONFIG_NS)) - return FILTER_ACCEPT; - const XMLCh* name=node->getLocalName(); - if (XMLString::equals(name,Applications) || - XMLString::equals(name,AttributeFactory) || - XMLString::equals(name,Credentials) || - XMLString::equals(name,CredentialsProvider) || - XMLString::equals(name,Extensions::LOCAL_NAME) || - XMLString::equals(name,Implementation) || - XMLString::equals(name,Listener) || - XMLString::equals(name,MemoryListener) || - XMLString::equals(name,MemorySessionCache) || - XMLString::equals(name,RequestMapProvider) || - XMLString::equals(name,_ReplayCache) || - XMLString::equals(name,_SessionCache) || - XMLString::equals(name,_StorageService) || - XMLString::equals(name,TCPListener) || - XMLString::equals(name,UnixListener)) - return FILTER_REJECT; - - return FILTER_ACCEPT; -} - -void XMLConfigImpl::doExtensions(const DOMElement* e, const char* label, Category& log) -{ - const DOMElement* exts=XMLHelper::getFirstChildElement(e,Extensions::LOCAL_NAME); - if (exts) { - exts=XMLHelper::getFirstChildElement(exts,Library); - while (exts) { - xmltooling::auto_ptr_char path(exts->getAttributeNS(NULL,_path)); - try { - if (path.get()) { - // TODO: replace with xmltooling extension load... - SAMLConfig::getConfig().saml_register_extension(path.get(),(void*)exts); - log.debug("loaded %s extension library (%s)", label, path.get()); - } - } - catch (exception& e) { - const XMLCh* fatal=exts->getAttributeNS(NULL,fatal); - if (fatal && (*fatal==chLatin_t || *fatal==chDigit_1)) { - log.fatal("unable to load mandatory %s extension library %s: %s", label, path.get(), e.what()); - throw; - } - else { - log.crit("unable to load optional %s extension library %s: %s", label, path.get(), e.what()); - } - } - exts=XMLHelper::getNextSiblingElement(exts,Library); - } - } -} - -XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer) : m_outer(outer), m_requestMapper(NULL) -{ -#ifdef _DEBUG - xmltooling::NDC ndc("XMLConfigImpl"); -#endif - Category& log=Category::getInstance(SHIBT_LOGCAT".Config"); - - try { - SPConfig& conf=SPConfig::getConfig(); - XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig(); - const DOMElement* SHAR=XMLHelper::getFirstChildElement(e,OutOfProcess); - if (!SHAR) - SHAR=XMLHelper::getFirstChildElement(e,Global); - const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e,InProcess); - if (!SHIRE) - SHIRE=XMLHelper::getFirstChildElement(e,Local); - - // Initialize log4cpp manually in order to redirect log messages as soon as possible. - if (conf.isEnabled(SPConfig::Logging)) { - const XMLCh* logconf=NULL; - if (conf.isEnabled(SPConfig::OutOfProcess)) - logconf=SHAR->getAttributeNS(NULL,logger); - else if (conf.isEnabled(SPConfig::InProcess)) - logconf=SHIRE->getAttributeNS(NULL,logger); - if (!logconf || !*logconf) - logconf=e->getAttributeNS(NULL,logger); - if (logconf && *logconf) { - xmltooling::auto_ptr_char logpath(logconf); - log.debug("loading new logging configuration from (%s), check log destination for status of configuration",logpath.get()); - XMLToolingConfig::getConfig().log_config(logpath.get()); - } - - if (first) - m_outer->m_tranLog = new TransactionLog(); - } - - // First load any property sets. - map root_remap; - root_remap["Global"]="OutOfProcess"; - root_remap["Local"]="InProcess"; - load(e,log,this,&root_remap); - - const DOMElement* child; - string plugtype; - - // Much of the processing can only occur on the first instantiation. - if (first) { - // Set clock skew. - pair skew=getUnsignedInt("clockSkew"); - if (skew.first) - xmlConf.clock_skew_secs=skew.second; - - // Extensions - doExtensions(e, "global", log); - if (conf.isEnabled(SPConfig::OutOfProcess)) - doExtensions(SHAR, "out of process", log); - - if (conf.isEnabled(SPConfig::InProcess)) - doExtensions(SHIRE, "in process", log); - - // Instantiate the ListenerService and SessionCache objects. - if (conf.isEnabled(SPConfig::Listener)) { - child=XMLHelper::getFirstChildElement(SHAR,UnixListener); - if (child) - plugtype=UNIX_LISTENER_SERVICE; - else { - child=XMLHelper::getFirstChildElement(SHAR,TCPListener); - if (child) - plugtype=TCP_LISTENER_SERVICE; - else { - child=XMLHelper::getFirstChildElement(SHAR,MemoryListener); - if (child) - plugtype=MEMORY_LISTENER_SERVICE; - else { - child=XMLHelper::getFirstChildElement(SHAR,Listener); - if (child) { - xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type)); - if (type.get()) - plugtype=type.get(); - } - } - } - } - if (child) { - log.info("building ListenerService of type %s...", plugtype.c_str()); - m_outer->m_listener = conf.ListenerServiceManager.newPlugin(plugtype.c_str(),child); - } - else { - log.fatal("can't build ListenerService, missing conf:Listener element?"); - throw ConfigurationException("Can't build ListenerService, missing conf:Listener element?"); - } - } - - if (conf.isEnabled(SPConfig::Caching)) { - // TODO: This code's a mess, due to a very bad config layout for the caches... - // Needs rework with the new config file. - const DOMElement* container=conf.isEnabled(SPConfig::OutOfProcess) ? SHAR : SHIRE; - - // First build any StorageServices. - string inmemID; - child=XMLHelper::getFirstChildElement(container,_StorageService); - while (child) { - xmltooling::auto_ptr_char id(child->getAttributeNS(NULL,Id)); - xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type)); - if (id.get() && type.get()) { - try { - log.info("building StorageService (%s) of type %s...", id.get(), type.get()); - m_outer->m_storage[id.get()] = xmlConf.StorageServiceManager.newPlugin(type.get(),child); - if (!strcmp(type.get(),MEMORY_STORAGE_SERVICE)) - inmemID = id.get(); - } - catch (exception& ex) { - log.crit("failed to instantiate StorageService (%s): %s", id.get(), ex.what()); - } - } - child=XMLHelper::getNextSiblingElement(container,_StorageService); - } - - child=XMLHelper::getFirstChildElement(container,_SessionCache); - if (child) { - xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type)); - log.info("building Session Cache of type %s...",type.get()); - m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(type.get(),child); - } - else if (conf.isEnabled(SPConfig::OutOfProcess)) { - log.warn("custom SessionCache unspecified or no longer supported, building SessionCache of type %s...",STORAGESERVICE_SESSION_CACHE); - if (inmemID.empty()) { - inmemID = "memory"; - log.info("no StorageServices configured, providing in-memory version for legacy config"); - m_outer->m_storage[inmemID] = xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE,NULL); - } - child = container->getOwnerDocument()->createElementNS(NULL,_SessionCache); - xmltooling::auto_ptr_XMLCh ssid(inmemID.c_str()); - const_cast(child)->setAttributeNS(NULL,_StorageService,ssid.get()); - m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(STORAGESERVICE_SESSION_CACHE,child); - } - else { - log.warn("custom SessionCache unspecified or no longer supported, building SessionCache of type %s...",REMOTED_SESSION_CACHE); - m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(REMOTED_SESSION_CACHE,NULL); - } - - // Replay cache. - StorageService* replaySS=NULL; - child=XMLHelper::getFirstChildElement(container,_ReplayCache); - if (child) { - xmltooling::auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService)); - if (ssid.get() && *ssid.get()) { - replaySS = m_outer->m_storage[ssid.get()]; - if (replaySS) - log.info("building ReplayCache on top of StorageService (%s)...", ssid.get()); - else - log.crit("unable to locate StorageService (%s) in configuration", ssid.get()); - } - } - if (!replaySS) { - log.info("building ReplayCache using in-memory StorageService..."); - if (inmemID.empty()) { - inmemID = "memory"; - log.info("no StorageServices configured, providing in-memory version for legacy config"); - m_outer->m_storage[inmemID] = xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE,NULL); - } - replaySS = m_outer->m_storage[inmemID]; - } - xmlConf.setReplayCache(new ReplayCache(replaySS)); - } - } // end of first-time-only stuff - - // Back to the fully dynamic stuff...next up is the RequestMapper. - if (conf.isEnabled(SPConfig::RequestMapping)) { - child=XMLHelper::getFirstChildElement(SHIRE,RequestMapProvider); - if (child) { - xmltooling::auto_ptr_char type(child->getAttributeNS(NULL,_type)); - log.info("building RequestMapper of type %s...",type.get()); - m_requestMapper=conf.RequestMapperManager.newPlugin(type.get(),child); - } - else { - log.fatal("can't build RequestMapper, missing conf:RequestMapProvider element?"); - throw ConfigurationException("can't build RequestMapper, missing conf:RequestMapProvider element?"); - } - } - - // Now we load the credentials map. - if (conf.isEnabled(SPConfig::Credentials)) { - // Old format was to wrap it in a CredentialsProvider plugin, we're inlining that... - child = XMLHelper::getFirstChildElement(e,CredentialsProvider); - child = XMLHelper::getFirstChildElement(child ? child : e,Credentials); - if (child) { - // Step down and process resolvers. - child=XMLHelper::getFirstChildElement(child); - while (child) { - xmltooling::auto_ptr_char id(child->getAttributeNS(NULL,Id)); - if (!id.get() || !*(id.get())) { - log.warn("skipping CredentialsResolver with no Id attribute"); - child = XMLHelper::getNextSiblingElement(child); - continue; - } - - if (XMLString::equals(child->getLocalName(),FileResolver)) - plugtype=FILESYSTEM_CREDENTIAL_RESOLVER; - else { - xmltooling::auto_ptr_char c(child->getAttributeNS(NULL,_type)); - plugtype=c.get(); - } - - if (!plugtype.empty()) { - try { - CredentialResolver* cr= - XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(plugtype.c_str(),child); - m_credResolverMap[id.get()] = cr; - } - catch (exception& ex) { - log.crit("failed to instantiate CredentialResolver (%s): %s", id.get(), ex.what()); - } - } - else { - log.error("unknown type of CredentialResolver with Id (%s)", id.get()); - } - - child = XMLHelper::getNextSiblingElement(child); - } - } - } - - // Load the default application. This actually has a fixed ID of "default". ;-) - child=XMLHelper::getFirstChildElement(e,Applications); - if (!child) { - log.fatal("can't build default Application object, missing conf:Applications element?"); - throw ConfigurationException("can't build default Application object, missing conf:Applications element?"); - } - XMLApplication* defapp=new XMLApplication(m_outer,child); - m_appmap[defapp->getId()]=defapp; - - // Load any overrides. - child = XMLHelper::getFirstChildElement(child,_Application); - while (child) { - auto_ptr iapp(new XMLApplication(m_outer,child,defapp)); - if (m_appmap.find(iapp->getId())!=m_appmap.end()) - log.crit("found conf:Application element with duplicate Id attribute (%s), skipping it", iapp->getId()); - else - m_appmap[iapp->getId()]=iapp.release(); - - child = XMLHelper::getNextSiblingElement(child,_Application); - } - } - catch (exception&) { - this->~XMLConfigImpl(); - throw; - } -#ifndef _DEBUG - catch (...) { - this->~XMLConfigImpl(); - throw; - } -#endif -} - -XMLConfigImpl::~XMLConfigImpl() -{ - for_each(m_appmap.begin(),m_appmap.end(),xmltooling::cleanup_pair()); - ShibConfig::getConfig().clearAttributeMappings(); - for_each(m_attrFactories.begin(),m_attrFactories.end(),xmltooling::cleanup()); - for_each(m_credResolverMap.begin(),m_credResolverMap.end(),xmltooling::cleanup_pair()); - delete m_requestMapper; - if (m_document) - m_document->release(); -} - -pair XMLConfig::load() -{ - // Load from source using base class. - pair raw = ReloadableXMLFile::load(); - - // If we own it, wrap it. - XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL); - - XMLConfigImpl* impl = new XMLConfigImpl(raw.second,(m_impl==NULL),this); - - // If we held the document, transfer it to the impl. If we didn't, it's a no-op. - impl->setDocument(docjanitor.release()); - - delete m_impl; - m_impl = impl; - - return make_pair(false,(DOMElement*)NULL); -} diff --git a/shib-target/shib-paths.h.in b/shib-target/shib-paths.h.in deleted file mode 100644 index 677fc0e..0000000 --- a/shib-target/shib-paths.h.in +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2001-2005 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shib-paths.h.in -- source file for the (auto-generated) shib-paths.h - * used to define the default paths for SHIB's Target - * - * Created by: Derek Atkins - * - * $Id$ - */ - -#ifndef SHIB_PATHS_H -#define SHIB_PATHS_H - -/* - * SHIB_SCHEMAS defines the default location where the schemas will be installed. - */ -#define SHIB_SCHEMAS "@-PKGXMLDIR-@" - -/* - * SHIB_CONFIG defines the default location of the Shib Target Configuration File. - */ -#define SHIB_CONFIG "@-PKGSYSCONFDIR-@/shibboleth.xml" - -#endif /* SHIB_PATHS_H */ diff --git a/shib-target/shib-target.h b/shib-target/shib-target.h deleted file mode 100644 index 6297b2d..0000000 --- a/shib-target/shib-target.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * shib-target.h -- top-level header file for the SHIB Common Target Library - * - * Created by: Derek Atkins - * - * $Id$ - */ - -#ifndef SHIB_TARGET_H -#define SHIB_TARGET_H - -// New headers -#include -#include -#include -#include -#include -#include - -// Old headers -#include -#include - -#ifdef WIN32 -# ifndef SHIBTARGET_EXPORTS -# define SHIBTARGET_EXPORTS __declspec(dllimport) -# endif -# define SHIB_SCHEMAS "/opt/shibboleth-sp/share/xml/shibboleth" -# define SHIB_CONFIG "/opt/shibboleth-sp/etc/shibboleth/shibboleth.xml" -#else -# include -# define SHIBTARGET_EXPORTS -#endif - -namespace shibtarget { - - // Abstract APIs for access to configuration information - - /** - * Interface to Shibboleth Applications, which exposes most of the functionality - * required to process web requests or security protocol messages for resources - * associated with them. - * - * Applications are implementation-specific, but generally correspond to collections - * of resources related to one another in logical ways, such as a virtual host or - * a Java servlet context. Most complex configuration data is associated with an - * Application. Implementations should always expose an application named "default" - * as a last resort. - */ - struct SHIBTARGET_EXPORTS IApplication : public virtual shibsp::Application, - public virtual shibboleth::ShibBrowserProfile::ITokenValidator - { - // caller is borrowing object, must use within scope of config lock - virtual const saml::SAMLBrowserProfile* getBrowserProfile() const=0; - virtual const saml::SAMLBinding* getBinding(const XMLCh* binding) const=0; - - // caller is given ownership of object, must use and delete within scope of config lock - virtual saml::SAMLBrowserProfile::ArtifactMapper* getArtifactMapper() const=0; - - // general token validation based on conditions, signatures, etc. - virtual void validateToken( - saml::SAMLAssertion* token, - time_t t=0, - const opensaml::saml2md::RoleDescriptor* role=NULL, - const xmltooling::TrustEngine* trust=NULL - ) const=0; - - virtual ~IApplication() {} - }; - - /** - * OpenSAML binding hook - * - * Instead of wrapping the binding to deal with mutual authentication, we - * just use the HTTP hook functionality offered by OpenSAML. The hook will - * register "itself" as a globalCtx pointer with the SAML binding and the caller - * will declare and pass the embedded struct as callCtx for use by the hook. - */ - class ShibHTTPHook : virtual public saml::SAMLSOAPHTTPBinding::HTTPHook - { - public: - ShibHTTPHook(const xmltooling::TrustEngine* trust) : m_trust(trust) {} - virtual ~ShibHTTPHook() {} - - // Only hook we need here is for outgoing connection to server. - virtual bool outgoing(saml::HTTPClient* conn, void* globalCtx=NULL, void* callCtx=NULL); - - // Client declares a context object and pass as callCtx to send() method. - class ShibHTTPHookCallContext { - public: - ShibHTTPHookCallContext(const shibsp::PropertySet* credUse, const opensaml::saml2md::RoleDescriptor* role) - : m_credUse(credUse), m_role(role), m_hook(NULL), m_authenticated(false) {} - const ShibHTTPHook* getHook() {return m_hook;} - const shibsp::PropertySet* getCredentialUse() {return m_credUse;} - const opensaml::saml2md::RoleDescriptor* getRoleDescriptor() {return m_role;} - bool isAuthenticated() const {return m_authenticated;} - void setAuthenticated() {m_authenticated=true;} - - private: - const shibsp::PropertySet* m_credUse; - const opensaml::saml2md::RoleDescriptor* m_role; - ShibHTTPHook* m_hook; - bool m_authenticated; - friend class ShibHTTPHook; - }; - - const xmltooling::TrustEngine* getTrustEngine() const {return m_trust;} - private: - const xmltooling::TrustEngine* m_trust; - }; - - /** - * Interface to a cached user session. - * - * Cache entries provide implementations with access to the raw SAML information they - * need to publish or provide access to the data for applications to use. All creation - * or access to entries is through the ISessionCache interface, and callers must unlock - * the entry when finished using it, rather than explicitly freeing them. - */ - struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable - { - virtual const char* getClientAddress() const=0; - virtual const char* getProviderId() const=0; - virtual std::pair getSubject(bool xml=true, bool obj=false) const=0; - virtual const char* getAuthnContext() const=0; - virtual std::pair getTokens(bool xml=true, bool obj=false) const=0; - virtual std::pair getFilteredTokens(bool xml=true, bool obj=false) const=0; - virtual ~ISessionCacheEntry() {} - }; - - /** - * Interface to a sink for session cache events. - * - * All caches support registration of a backing store that can be informed - * of significant events in the lifecycle of a cache entry. - */ - struct SHIBTARGET_EXPORTS ISessionCacheStore - { - virtual HRESULT onCreate( - const char* key, - const IApplication* application, - const ISessionCacheEntry* entry, - int majorVersion, - int minorVersion, - time_t created - )=0; - virtual HRESULT onRead( - const char* key, - std::string& applicationId, - std::string& clientAddress, - std::string& providerId, - std::string& subject, - std::string& authnContext, - std::string& tokens, - int& majorVersion, - int& minorVersion, - time_t& created, - time_t& accessed - )=0; - virtual HRESULT onRead(const char* key, time_t& accessed)=0; - virtual HRESULT onRead(const char* key, std::string& tokens)=0; - virtual HRESULT onUpdate(const char* key, const char* tokens=NULL, time_t lastAccess=0)=0; - virtual HRESULT onDelete(const char* key)=0; - virtual ~ISessionCacheStore() {} - }; - - /** - * Interface to the session cache. - * - * The session cache abstracts a persistent (meaning across requests) cache of - * instances of the ISessionCacheEntry interface. Creation of new entries and entry - * lookup are confined to this interface to enable implementations to flexibly - * remote and/or optimize calls by implementing custom versions of the - * ISessionCacheEntry interface as required. - */ - struct SHIBTARGET_EXPORTS ISessionCache : virtual public shibsp::SessionCache - { - virtual std::string insert( - const IApplication* application, - const opensaml::saml2md::RoleDescriptor* source, - const char* client_addr, - const saml::SAMLSubject* subject, - const char* authnContext, - const saml::SAMLResponse* tokens - )=0; - virtual ISessionCacheEntry* find( - const char* key, const IApplication* application, const char* client_addr - )=0; - virtual void remove( - const char* key, const IApplication* application, const char* client_addr - )=0; - - virtual bool setBackingStore(ISessionCacheStore* store)=0; - virtual ~ISessionCache() {} - }; - - #define MEMORY_SESSIONCACHE "edu.internet2.middleware.shibboleth.sp.provider.MemorySessionCacheProvider" - #define MYSQL_SESSIONCACHE "edu.internet2.middleware.shibboleth.sp.provider.MySQLSessionCacheProvider" - #define ODBC_SESSIONCACHE "edu.internet2.middleware.shibboleth.sp.provider.ODBCSessionCacheProvider" - - #define MYSQL_REPLAYCACHE "edu.internet2.middleware.shibboleth.sp.provider.MySQLReplayCacheProvider" - #define ODBC_REPLAYCACHE "edu.internet2.middleware.shibboleth.sp.provider.ODBCReplayCacheProvider" - - - class SHIBTARGET_EXPORTS ShibTargetConfig - { - public: - ShibTargetConfig() {} - virtual ~ShibTargetConfig() {} - - virtual bool init(const char* schemadir) = 0; - virtual bool load(const char* config) = 0; - virtual void shutdown() = 0; - - static ShibTargetConfig& getConfig(); - }; - -} - -#endif /* SHIB_TARGET_H */ diff --git a/shib-target/shib-target.rc b/shib-target/shib-target.rc deleted file mode 100644 index 5050962..0000000 --- a/shib-target/shib-target.rc +++ /dev/null @@ -1,117 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 5,0,0,0 - PRODUCTVERSION 1,3,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "\0" - VALUE "CompanyName", "Internet2\0" - VALUE "FileDescription", "Shibboleth Target Library\0" - VALUE "FileVersion", "5, 0, 0, 0\0" -#ifdef _DEBUG - VALUE "InternalName", "shibtarget_5D\0" -#else - VALUE "InternalName", "shibtarget_5\0" -#endif - VALUE "LegalCopyright", "Copyright © 2005 Internet2\0" - VALUE "LegalTrademarks", "\0" -#ifdef _DEBUG - VALUE "OriginalFilename", "shibtarget_5D.dll\0" -#else - VALUE "OriginalFilename", "shibtarget_5.dll\0" -#endif - VALUE "PrivateBuild", "\0" - VALUE "ProductName", "Shibboleth 1.3\0" - VALUE "ProductVersion", "1, 3, 0, 0\0" - VALUE "SpecialBuild", "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // !_MAC - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/shib-target/shibtarget.dsp b/shib-target/shibtarget.dsp deleted file mode 100644 index 1a23b2b..0000000 --- a/shib-target/shibtarget.dsp +++ /dev/null @@ -1,177 +0,0 @@ -# Microsoft Developer Studio Project File - Name="shibtarget" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=shibtarget - 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 "shibtarget.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 "shibtarget.mak" CFG="shibtarget - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "shibtarget - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "shibtarget - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "shibtarget - 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 /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SHIBTARGET_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "." /I ".." /I "..\oncrpc" /I "..\..\..\opensaml\c" /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /D "_MBCS" /D "WANT_TCP_SHAR" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# 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 /nologo /dll /machine:I386 -# ADD LINK32 log4cpp.lib xerces-c_2.lib saml_5.lib wsock32.lib libeay32.lib ssleay32.lib /nologo /dll /machine:I386 /out:"Release/shibtarget_5.dll" /libpath:"..\..\..\opensaml\c\saml\Release" /libpath:"\openssl-0.9.7e\out32dll" -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "shibtarget - 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 /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SHIBTARGET_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "." /I ".." /I "..\oncrpc" /I "..\..\..\opensaml\c" /D "_WINDOWS" /D "WANT_TCP_SHAR" /D "WIN32" /D "_DEBUG" /D "_MBCS" /FR /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# 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 /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 log4cppD.lib xerces-c_2D.lib saml_5D.lib wsock32.lib libeay32.lib ssleay32.lib /nologo /dll /debug /machine:I386 /out:"Debug/shibtarget_5D.dll" /pdbtype:sept /libpath:"..\..\..\opensaml\c\saml\Debug" /libpath:"\openssl-0.9.7e\out32dll.dbg" -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "shibtarget - Win32 Release" -# Name "shibtarget - Win32 Debug" -# Begin Source File - -SOURCE=.\ArtifactMapper.cpp -# End Source File -# Begin Source File - -SOURCE=.\hresult.h -# End Source File -# Begin Source File - -SOURCE=.\internal.h -# End Source File -# Begin Source File - -SOURCE=.\MemoryListener.cpp -# End Source File -# Begin Source File - -SOURCE=.\resource.h -# End Source File -# Begin Source File - -SOURCE=.\RPCListener.cpp -# End Source File -# Begin Source File - -SOURCE=".\shib-ccache.cpp" -# End Source File -# Begin Source File - -SOURCE=".\shib-config.cpp" -# End Source File -# Begin Source File - -SOURCE=".\shib-handlers.cpp" -# End Source File -# Begin Source File - -SOURCE=".\shib-ini.cpp" -# End Source File -# Begin Source File - -SOURCE=".\shib-mlp.cpp" -# End Source File -# Begin Source File - -SOURCE=".\shib-sock.cpp" -# End Source File -# Begin Source File - -SOURCE=".\shib-target.cpp" -# End Source File -# Begin Source File - -SOURCE=".\shib-target.h" -# End Source File -# Begin Source File - -SOURCE=".\shib-target.rc" -# End Source File -# Begin Source File - -SOURCE=.\ShibHTTPHook.cpp -# End Source File -# Begin Source File - -SOURCE=".\shibrpc-clnt.c" -# End Source File -# Begin Source File - -SOURCE=".\shibrpc-xdr.c" -# End Source File -# Begin Source File - -SOURCE=.\shibrpc.h -# End Source File -# Begin Source File - -SOURCE=.\XML.cpp -# End Source File -# Begin Source File - -SOURCE=.\XMLRequestMapper.cpp -# End Source File -# End Target -# End Project diff --git a/shib-target/shibtarget.vcproj b/shib-target/shibtarget.vcproj deleted file mode 100644 index 4a6d6eb..0000000 --- a/shib-target/shibtarget.vcproj +++ /dev/null @@ -1,259 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -