EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{31B171C1-E06C-464F-A541-38724AB52D79}"
ProjectSection(SolutionItems) = preProject
- acinclude.m4 = acinclude.m4
- acx_pthread.m4 = acx_pthread.m4
- bootstrap = bootstrap
+ m4\acinclude.m4 = m4\acinclude.m4
+ m4\acx_pthread.m4 = m4\acx_pthread.m4
config_win32.h = config_win32.h
configure.ac = configure.ac
- depend = depend
doxygen.am = doxygen.am
doxygen.cfg = doxygen.cfg
- doxygen.m4 = doxygen.m4
- libtool.m4 = libtool.m4
- ltmain.sh = ltmain.sh
+ m4\doxygen.m4 = m4\doxygen.m4
Makefile.am = Makefile.am
pkginfo.in = pkginfo.in
Portfile.in = Portfile.in
# define _CRT_SECURE_NO_DEPRECATE 1
#endif
+#include <shibsp/exceptions.h>
#include <shibsp/AbstractSPRequest.h>
#include <shibsp/AccessControl.h>
-#include <shibsp/exceptions.h>
+#include <shibsp/GSSRequest.h>
#include <shibsp/RequestMapper.h>
#include <shibsp/SPConfig.h>
#include <shibsp/ServiceProvider.h>
#include <shibsp/SessionCache.h>
#include <shibsp/attribute/Attribute.h>
+
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/regx/RegularExpression.hpp>
#include <xmltooling/XMLToolingConfig.h>
string g_unsetHeaderValue,g_spoofKey;
bool g_checkSpoofing = true;
bool g_catchAll = false;
- static const char* g_UserDataKey = "_shib_check_user_";
+#ifndef SHIB_APACHE_13
+ char* g_szGSSContextKey = "mod_auth_gssapi:gss_ctx";
+#endif
+ static const char* g_UserDataKey = "urn:mace:shibboleth:Apache:shib_check_user";
}
/* Apache 2.2.x headers must be accumulated and set in the output filter.
return nullptr;
}
-/********************************************************************************/
-// Apache ShibTarget subclass(es) here.
class ShibTargetApache : public AbstractSPRequest
+#if defined(HAVE_GSSAPI) && !defined(SHIB_APACHE_13)
+ , public GSSRequest
+#endif
{
bool m_handler;
mutable string m_body;
}
long returnDecline(void) { return DECLINED; }
long returnOK(void) { return OK; }
+#if defined(HAVE_GSSAPI) && !defined(SHIB_APACHE_13)
+ gss_ctx_id_t getGSSContext() const {
+ gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
+ apr_pool_userdata_get((void**)&ctx, g_szGSSContextKey, m_req->pool);
+ return ctx;
+ }
+#endif
};
/********************************************************************************/
status = true;
}
else if (!strcmp(w,"user") && !remote_user.empty()) {
- bool regexp=false,negate=false;
+ bool regexp = false;
while (*t) {
- w=ap_getword_conf(sta->m_req->pool,&t);
- if (*w=='~') {
- regexp=true;
+ w = ap_getword_conf(sta->m_req->pool,&t);
+ if (*w == '~') {
+ regexp = true;
continue;
}
- else if (*w=='!') {
- negate=true;
- if (*(w+1)=='~')
- regexp=true;
+ else if (*w == '!') {
+ // A negated rule presumes success unless a match is found.
+ status = true;
+ if (*(w+1) == '~')
+ regexp = true;
continue;
}
string("htaccess plugin caught exception while parsing regular expression (") + w + "): " + tmp.get());
}
}
- else if (remote_user==w) {
+ else if (remote_user == w) {
match = true;
}
if (match) {
- // If we matched, then we're done with this rule either way and status is set to reflect the outcome.
- status = !negate;
+ // If we matched, then we're done with this rule either way and we flip status to reflect the outcome.
+ status = !status;
if (request.isPriorityEnabled(SPRequest::SPDebug))
request.log(SPRequest::SPDebug,
- string("htaccess: require user ") + (negate ? "rejecting (" : "accepting (") + remote_user + ")");
+ string("htaccess: require user ") + (!status ? "rejecting (" : "accepting (") + remote_user + ")");
break;
}
}
}
else if (!strcmp(w,"group") && !remote_user.empty()) {
- SH_AP_TABLE* grpstatus=nullptr;
+ SH_AP_TABLE* grpstatus = nullptr;
if (sta->m_dc->szAuthGrpFile) {
if (request.isPriorityEnabled(SPRequest::SPDebug))
request.log(SPRequest::SPDebug,string("htaccess plugin using groups file: ") + sta->m_dc->szAuthGrpFile);
- grpstatus=groups_for_user(sta->m_req,remote_user.c_str(),sta->m_dc->szAuthGrpFile);
+ grpstatus = groups_for_user(sta->m_req,remote_user.c_str(),sta->m_dc->szAuthGrpFile);
}
- bool negate=false;
while (*t) {
- w=ap_getword_conf(sta->m_req->pool,&t);
- if (*w=='!') {
- negate=true;
+ w = ap_getword_conf(sta->m_req->pool,&t);
+ if (*w == '!') {
+ // A negated rule presumes success unless a match is found.
+ status = true;
continue;
}
if (grpstatus && ap_table_get(grpstatus,w)) {
- // If we matched, then we're done with this rule either way and status is set to reflect the outcome.
- status = !negate;
- request.log(SPRequest::SPDebug, string("htaccess: require group ") + (negate ? "rejecting (" : "accepting (") + w + ")");
+ // If we matched, then we're done with this rule either way and we flip status to reflect the outcome.
+ status = !status;
+ request.log(SPRequest::SPDebug, string("htaccess: require group ") + (!status ? "rejecting (" : "accepting (") + w + ")");
break;
}
}
}
else if (!strcmp(w,"authnContextClassRef") || !strcmp(w,"authnContextDeclRef")) {
const char* ref = !strcmp(w,"authnContextClassRef") ? session->getAuthnContextClassRef() : session->getAuthnContextDeclRef();
- bool regexp=false,negate=false;
- while (ref && *t) {
- w=ap_getword_conf(sta->m_req->pool,&t);
- if (*w=='~') {
- regexp=true;
- continue;
- }
- else if (*w=='!') {
- negate=true;
- if (*(w+1)=='~')
+ if (ref && *ref) {
+ bool regexp = false;
+ while (ref && *t) {
+ w = ap_getword_conf(sta->m_req->pool,&t);
+ if (*w == '~') {
regexp=true;
- continue;
- }
+ continue;
+ }
+ else if (*w == '!') {
+ // A negated rule presumes success unless a match is found.
+ status = true;
+ if (*(w+1)=='~')
+ regexp = true;
+ continue;
+ }
- // Figure out if there's a match.
- bool match = false;
- if (regexp) {
- try {
- // To do regex matching, we have to convert from UTF-8.
- RegularExpression re(w);
- match = re.matches(ref);
+ // Figure out if there's a match.
+ bool match = false;
+ if (regexp) {
+ try {
+ // To do regex matching, we have to convert from UTF-8.
+ RegularExpression re(w);
+ match = re.matches(ref);
+ }
+ catch (XMLException& ex) {
+ auto_ptr_char tmp(ex.getMessage());
+ request.log(SPRequest::SPError,
+ string("htaccess plugin caught exception while parsing regular expression (") + w + "): " + tmp.get());
+ }
}
- catch (XMLException& ex) {
- auto_ptr_char tmp(ex.getMessage());
- request.log(SPRequest::SPError,
- string("htaccess plugin caught exception while parsing regular expression (") + w + "): " + tmp.get());
+ else if (!strcmp(w,ref)) {
+ match = true;
}
- }
- else if (!strcmp(w,ref)) {
- match = true;
- }
- if (match) {
- // If we matched, then we're done with this rule either way and status is set to reflect the outcome.
- status = !negate;
- if (request.isPriorityEnabled(SPRequest::SPDebug))
- request.log(SPRequest::SPDebug,
- string("htaccess: require authnContext ") + (negate ? "rejecting (" : "accepting (") + ref + ")");
- break;
+ if (match) {
+ // If we matched, then we're done with this rule either way and we flip status to reflect the outcome.
+ status = !status;
+ if (request.isPriorityEnabled(SPRequest::SPDebug))
+ request.log(SPRequest::SPDebug,
+ string("htaccess: require authnContext ") + (!status ? "rejecting (" : "accepting (") + ref + ")");
+ break;
+ }
}
}
+ else if (request.isPriorityEnabled(SPRequest::SPDebug)) {
+ request.log(SPRequest::SPDebug, "htaccess: require authnContext rejecting session with no context associated");
+ }
}
else if (!session) {
request.log(SPRequest::SPError, string("htaccess: require ") + w + " not given a valid session, are you using lazy sessions?");
OR_AUTHCFG, TAKE1, "Set Shibboleth applicationId property for content"},
{"ShibBasicHijack", (config_fn_t)ap_set_flag_slot,
(void *) XtOffsetOf (shib_dir_config, bBasicHijack),
- OR_AUTHCFG, FLAG, "Respond to AuthType Basic and convert to shibboleth"},
+ OR_AUTHCFG, FLAG, "(DEPRECATED) Respond to AuthType Basic and convert to shibboleth"},
{"ShibRequireSession", (config_fn_t)ap_set_flag_slot,
(void *) XtOffsetOf (shib_dir_config, bRequireSession),
OR_AUTHCFG, FLAG, "Initiates a new session if one does not exist"},
#elif defined(SHIB_APACHE_20) || defined(SHIB_APACHE_22)
+//static const char * const authnPre[] = { "mod_gss.c", nullptr };
+
extern "C" void shib_register_hooks (apr_pool_t *p)
{
#ifdef SHIB_DEFERRED_HEADERS
ap_hook_post_read_request(shib_post_read, nullptr, nullptr, APR_HOOK_MIDDLE);
#endif
ap_hook_child_init(shib_child_init, nullptr, nullptr, APR_HOOK_MIDDLE);
- ap_hook_check_user_id(shib_check_user, nullptr, nullptr, APR_HOOK_MIDDLE);
+ const char* prereq = getenv("SHIBSP_APACHE_PREREQ");
+ if (prereq && *prereq) {
+ const char* const authnPre[] = { prereq, nullptr };
+ ap_hook_check_user_id(shib_check_user, authnPre, nullptr, APR_HOOK_MIDDLE);
+ }
+ else {
+ ap_hook_check_user_id(shib_check_user, nullptr, nullptr, APR_HOOK_MIDDLE);
+ }
ap_hook_auth_checker(shib_auth_checker, nullptr, nullptr, APR_HOOK_FIRST);
ap_hook_handler(shib_handler, nullptr, nullptr, APR_HOOK_LAST);
ap_hook_fixups(shib_fixups, nullptr, nullptr, APR_HOOK_MIDDLE);
RSRC_CONF, "Path to shibboleth2.xml config file"),
AP_INIT_TAKE1("ShibCatalogs", (config_fn_t)ap_set_global_string_slot, &g_szSchemaDir,
RSRC_CONF, "Paths of XML schema catalogs"),
+ AP_INIT_TAKE1("ShibGSSKey", (config_fn_t)ap_set_global_string_slot, &g_szGSSContextKey,
+ RSRC_CONF, "Name of user data key containing GSS context established by GSS module"),
AP_INIT_TAKE1("ShibURLScheme", (config_fn_t)shib_set_server_string_slot,
(void *) offsetof (shib_server_config, szScheme),
OR_AUTHCFG, "Set Shibboleth applicationId property for content"),
AP_INIT_FLAG("ShibBasicHijack", (config_fn_t)ap_set_flag_slot,
(void *) offsetof (shib_dir_config, bBasicHijack),
- OR_AUTHCFG, "Respond to AuthType Basic and convert to shibboleth"),
+ OR_AUTHCFG, "(DEPRECATED) Respond to AuthType Basic and convert to shibboleth"),
AP_INIT_FLAG("ShibRequireSession", (config_fn_t)ap_set_flag_slot,
(void *) offsetof (shib_dir_config, bRequireSession),
OR_AUTHCFG, "Initiates a new session if one does not exist"),
#! /bin/sh
+DECLS=1
+
SAML1=0
SAML2=0
ARTIFACT=0
SAML1POST="urn:oasis:names:tc:SAML:1.0:profiles:browser-post"
SAML1ART="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01"
-while getopts a:c:e:f:h:n:o:s:t:u:12ADLN c
+while getopts a:c:e:f:h:n:o:s:t:u:12ADLNO c
do
case $c in
c) CERTS[${#CERTS[*]}]=$OPTARG;;
D) DS=1;;
L) LOGOUT=1;;
N) NAMEIDMGMT=1;;
- \?) echo metagen [-12ADLN] -c cert1 [-c cert2 ...] -h host1 [-h host2 ...] [-e entityID]
+ O) DECLS=0;;
+ \?) echo metagen [-12ADLNO] -c cert1 [-c cert2 ...] -h host1 [-h host2 ...] [-e entityID]
exit 1;;
esac
done
done
if [ -z $ENTITYID ] ; then
- ENTITYID=https://${HOSTS[0]}/shibboleth
+ if [ ${#HOSTS[*]} -eq 0 ] ; then
+ ENTITYID=https://${NAKEDHOSTS[0]}/shibboleth
+ else
+ ENTITYID=https://${HOSTS[0]}/shibboleth
+ fi
fi
# Establish protocols and bindings.
fi
if [ $SAML1 -eq 1 -a $SAML2 -eq 1 ] ; then
- PROTENUM="$SAML20PROT $SAML11PROT $SAML10PROT"
+ PROTENUM="$SAML20PROT $SAML11PROT"
elif [ $SAML1 -eq 1 ] ; then
- PROTENUM="$SAML11PROT $SAML10PROT"
+ PROTENUM="$SAML11PROT"
else
PROTENUM="$SAML20PROT"
fi
ACSLOC[${#ACSLOC[*]}]="SAML2/ECP"
fi
+if [ $DECLS -eq 1 ] ; then
+ DECLS="xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" "
+ if [ $DS -eq 1 ] ; then
+ DECLS="${DECLS}xmlns:disco=\"urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol\" "
+ fi
+else
+ DECLS=""
+fi
+
cat <<EOF
-<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="${ENTITYID}">
+<md:EntityDescriptor ${DECLS}entityID="${ENTITYID}">
<md:SPSSODescriptor protocolSupportEnumeration="${PROTENUM}">
EOF
for h in ${HOSTS[@]}
do
cat << EOF
- <DiscoveryResponse xmlns="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://$h/Shibboleth.sso/DS" index="$count"/>
+ <disco:DiscoveryResponse Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://$h/Shibboleth.sso/DS" index="$count"/>
EOF
let "count++"
done
for h in ${NAKEDHOSTS[@]}
do
cat << EOF
- <DiscoveryResponse xmlns="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="http://$h/Shibboleth.sso/DS" index="$count"/>
+ <disco:DiscoveryResponse xmlns="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="http://$h/Shibboleth.sso/DS" index="$count"/>
EOF
let "count++"
done
EOF
fi
-for c in ${ADMIN[@]}
+count=${#ADMIN[*]}
+for (( i=0; i<count; i++ ))
do
- c=(${c//\// })
+ IFS="/"; declare -a c=(${ADMIN[$i]})
cat <<EOF
<md:ContactPerson contactType="administrative">
<md:GivenName>${c[0]}</md:GivenName>
EOF
done
-for c in ${SUP[@]}
+count=${#SUP[*]}
+for (( i=0; i<count; i++ ))
do
- c=(${c//\// })
+ IFS="/"; declare -a c=(${SUP[$i]})
cat <<EOF
<md:ContactPerson contactType="support">
<md:GivenName>${c[0]}</md:GivenName>
EOF
done
-for c in ${TECH[@]}
+count=${#TECH[*]}
+for (( i=0; i<count; i++ ))
do
- c=(${c//\// })
+ IFS="/"; declare -a c=(${TECH[$i]})
cat <<EOF
<md:ContactPerson contactType="technical">
<md:GivenName>${c[0]}</md:GivenName>
cat <<EOF
</md:EntityDescriptor>
+
EOF
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Short-Description: Shibboleth 2.x Service Provider Daemon
-# Description: Starts the separate daemon used by the Shibboleth
-# Apache module to manage state and SAML interactions.
+# Description: Starts the separate daemon used by the Shibboleth Apache module to manage state and SAML interactions.
### END INIT INFO
#
-AC_PREREQ([2.67])
+AC_PREREQ([2.50])
AC_INIT([shibboleth],[2.4],[https://bugs.internet2.edu/],[shibboleth])
AC_CONFIG_SRCDIR(shibsp)
AC_CONFIG_AUX_DIR(build-aux)
AC_CONFIG_MACRO_DIR(m4)
AM_INIT_AUTOMAKE
-LT_INIT
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
# Docygen features
DX_HTML_FEATURE(ON)
AC_PROG_CC([gcc gcc3 cc])
AC_PROG_CXX([g++ g++3 c++ CC])
-AC_DISABLE_STATIC
AC_CANONICAL_HOST
if test "$GCC" = "yes" ; then
# Checks for library functions.
AC_FUNC_STRFTIME
AC_FUNC_STRERROR_R
+AC_CHECK_HEADERS([sys/utsname.h])
AC_CHECK_FUNCS([strchr strdup strstr timegm gmtime_r strtok_r strcasecmp])
# checks for pthreads
# Thank you Solaris, really.
AC_MSG_CHECKING(for ctime_r)
if test -z "$ac_cv_ctime_args"; then
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[
- time_t clock;
- char buf[26];
- ctime_r(&clock, buf);
- ]])],[ac_cv_ctime_args=2],[])
-
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>]], [[
- time_t clock;
- char buf[26];
- ctime_r(&clock, buf, 26);
- ]])],[ac_cv_ctime_args=3],[])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <time.h>]], [[time_t clock; char buf[26]; ctime_r(&clock, buf);]])],
+ [ac_cv_ctime_args=2],[])
+
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <time.h>]], [[time_t clock; char buf[26]; ctime_r(&clock, buf, 26);]])],
+ [ac_cv_ctime_args=3],[])
fi
if test -z "$ac_cv_ctime_args"; then
AC_MSG_RESULT(no)
else
if test "$ac_cv_ctime_args" = 2; then
- AC_DEFINE(HAVE_CTIME_R_2,1,[Define if ctime_r is present with 2 parameters.])
+ AC_DEFINE([HAVE_CTIME_R_2],[1],[Define if ctime_r is present with 2 parameters.])
elif test "$ac_cv_ctime_args" = 3; then
- AC_DEFINE(HAVE_CTIME_R_3,1,[Define if ctime_r is present with 3 parameters.])
+ AC_DEFINE([HAVE_CTIME_R_3],[1],[Define if ctime_r is present with 3 parameters.])
fi
AC_MSG_RESULT([yes, and it takes $ac_cv_ctime_args arguments])
fi
[AC_MSG_RESULT([no])])
AC_MSG_CHECKING([whether Xerces DOMNodeFilter API returns a short])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <xercesc/dom/DOM.hpp>]], [[using namespace XERCES_CPP_NAMESPACE;
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <xercesc/dom/DOM.hpp>]],
+ [[using namespace XERCES_CPP_NAMESPACE;
class Blocker : public DOMNodeFilter {
public:
short acceptNode(const DOMNode* node) const {
}
};
static Blocker g_Blocker;
- ]])],[AC_MSG_RESULT([yes])
- AC_DEFINE([SHIBSP_XERCESC_SHORT_ACCEPTNODE],[1],[Define to 1 if Xerces DOMNodeFilter API returns a short.])],[AC_MSG_RESULT([no])])
+ ]])],
+ [AC_MSG_RESULT([yes])AC_DEFINE([SHIBSP_XERCESC_SHORT_ACCEPTNODE],[1],[Define to 1 if Xerces DOMNodeFilter API returns a short.])],
+ [AC_MSG_RESULT([no])])
#XML-Tooling settings
AC_ARG_WITH(xmltooling,
LIBS="$XMLSEC_LIBS $LIBS"
AC_CHECK_HEADER([saml/saml2/metadata/Metadata.h],,AC_MSG_ERROR([unable to find OpenSAML header files]))
-AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#include <saml/SAMLConfig.h>
-#include <saml/version.h>
- ]], [[
-#if _OPENSAML_VERSION >= 20400
+AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[#include <saml/SAMLConfig.h>
+#include <saml/version.h>]],
+[[#if _OPENSAML_VERSION >= 20400
opensaml::SAMLConfig::getConfig();
#else
#error Need OpenSAML version 2.4 or higher
-#endif
- ]])],[AC_DEFINE(HAVE_SAML,1,[Define if saml library was found])],[AC_MSG_ERROR([unable to link with OpenSAML, or version was too old])
+#endif]])],
+ ,[AC_MSG_ERROR([unable to link with OpenSAML, or version was too old])
])
# restore master libs
save_LIBS="$LIBS"
LIBS="$LIBS $ODBC_LIBS"
AC_MSG_CHECKING(if we can link againt ODBC)
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sql.h>
- #include <sqlext.h>
- #include <stdio.h>]], [[SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV, 0)]])],[have_odbc_libs=yes],[have_odbc_libs=no])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[#include <sql.h>
+ #include <sqlext.h>
+ #include <stdio.h>]],
+ [[SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV, 0)]])],
+ [have_odbc_libs=yes],[have_odbc_libs=no])
LIBS="$save_LIBS"
-
if test "$have_odbc_libs" = no ; then
if test "$odbc_enabled" = "yes" ; then
AC_MSG_ERROR([unable to link with ODBC Library])
AC_SUBST(ODBC_LIBS)
fi
+# GSS-API checking
+
+GSSAPI_ROOT="/usr"
+AC_ARG_WITH(gssapi-includes,
+ AS_HELP_STRING([--with-gssapi-includes=DIR],[Specify location of GSSAPI header]),
+ [ GSSAPI_INCS="-I$withval"
+ want_gss="yes" ]
+)
+
+AC_ARG_WITH(gssapi-libs,
+ AS_HELP_STRING([--with-gssapi-libs=DIR],[Specify location of GSSAPI libs]),
+ [ GSSAPI_LIB_DIR="-L$withval"
+ want_gss="yes" ]
+)
+
+AC_ARG_WITH(gssapi,
+ AS_HELP_STRING([--with-gssapi=DIR],[Where to look for GSSAPI]),
+ [ GSSAPI_ROOT="$withval"
+ if test x"$GSSAPI_ROOT" != xno; then
+ want_gss="yes"
+ if test x"$GSSAPI_ROOT" = xyes; then
+ dnl if yes, then use default root
+ GSSAPI_ROOT="/usr"
+ fi
+ fi
+])
+
+save_CPPFLAGS="$CPPFLAGS"
+AC_MSG_CHECKING([if GSSAPI support is requested])
+if test x"$want_gss" = xyes; then
+ AC_MSG_RESULT(yes)
+
+ if test -z "$GSSAPI_INCS"; then
+ if test -f "$GSSAPI_ROOT/bin/krb5-config"; then
+ GSSAPI_INCS=`$GSSAPI_ROOT/bin/krb5-config --cflags gssapi`
+ elif test "$GSSAPI_ROOT" != "yes"; then
+ GSSAPI_INCS="-I$GSSAPI_ROOT/include"
+ fi
+ fi
+
+ CPPFLAGS="$CPPFLAGS $GSSAPI_INCS"
+
+ AC_CHECK_HEADER(gss.h,
+ [
+ dnl found in the given dirs
+ AC_DEFINE([HAVE_GSSGNU],[1],[if you have the GNU gssapi libraries])
+ gnu_gss=yes
+ ],
+ [
+ dnl not found, check Heimdal or MIT
+ AC_CHECK_HEADERS([gssapi/gssapi.h], [], [not_mit=1])
+ AC_CHECK_HEADERS(
+ [gssapi/gssapi_generic.h gssapi/gssapi_krb5.h],
+ [],
+ [not_mit=1],
+ [
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_GSSAPI_GSSAPI_H
+#include <gssapi/gssapi.h>
+#endif
+ ])
+ if test "x$not_mit" = "x1"; then
+ dnl MIT not found, check for Heimdal
+ AC_CHECK_HEADER([gssapi.h],
+ [
+ dnl found
+ AC_DEFINE([HAVE_GSSHEIMDAL],[1],[if you have the Heimdal gssapi libraries])
+ ],
+ [
+ dnl no header found, disabling GSS
+ want_gss=no
+ AC_MSG_WARN([disabling GSSAPI since no header files was found])
+ ]
+ )
+ else
+ dnl MIT found
+ AC_DEFINE([HAVE_GSSMIT],[1],[if you have the MIT gssapi libraries])
+ dnl check if we have a really old MIT kerberos (<= 1.2)
+ AC_MSG_CHECKING([if gssapi headers declare GSS_C_NT_HOSTBASED_SERVICE])
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <gssapi/gssapi_krb5.h>
+ ]],[[
+ gss_import_name(
+ (OM_uint32 *)0,
+ (gss_buffer_t)0,
+ GSS_C_NT_HOSTBASED_SERVICE,
+ (gss_name_t *)0);
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
+ ],[
+ AC_MSG_RESULT([no])
+ AC_DEFINE([HAVE_OLD_GSSMIT],[1],[if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE])
+ ])
+ fi
+ ]
+ )
+else
+ AC_MSG_RESULT(no)
+fi
+if test x"$want_gss" = xyes; then
+ AC_DEFINE([HAVE_GSSAPI],[1],[if you have the gssapi libraries])
+
+ if test -n "$gnu_gss"; then
+ LDFLAGS="$LDFLAGS $GSSAPI_LIB_DIR"
+ LIBS="$LIBS -lgss"
+ elif test -z "$GSSAPI_LIB_DIR"; then
+ case $host in
+ *-*-darwin*)
+ LIBS="$LIBS -lgssapi_krb5 -lresolv"
+ ;;
+ *)
+ if test -f "$GSSAPI_ROOT/bin/krb5-config"; then
+ dnl krb5-config doesn't have --libs-only-L or similar, put everything
+ dnl into LIBS
+ gss_libs=`$GSSAPI_ROOT/bin/krb5-config --libs gssapi`
+ LIBS="$LIBS $gss_libs"
+ elif test "$GSSAPI_ROOT" != "yes"; then
+ LDFLAGS="$LDFLAGS -L$GSSAPI_ROOT/lib$libsuff"
+ LIBS="$LIBS -lgssapi"
+ else
+ LIBS="$LIBS -lgssapi"
+ fi
+ ;;
+ esac
+ else
+ LDFLAGS="$LDFLAGS $GSSAPI_LIB_DIR"
+ LIBS="$LIBS -lgssapi"
+ fi
+else
+ CPPFLAGS="$save_CPPFLAGS"
+fi
+
AC_SUBST(WANT_SUBDIRS)
This project includes software developed by the National Research Council
of Canada.
+
+This project includes software developed by the Danish CLARIN Consortium.
</complexContent>
</complexType>
+ <complexType name="Base64AttributeDecoder">
+ <annotation>
+ <documentation>
+ Decoder for attributes with base64-encoded string values.
+ </documentation>
+ </annotation>
+ <complexContent>
+ <extension base="am:AttributeDecoderType" />
+ </complexContent>
+ </complexType>
+
</schema>
<schema targetNamespace="urn:mace:shibboleth:2.0:native:sp:config"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:conf="urn:mace:shibboleth:2.0:native:sp:config"
- xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
<attribute name="checkSpoofing" type="boolean"/>
<attribute name="spoofKey" type="conf:string"/>
<attribute name="catchAll" type="boolean"/>
+ <attribute name="extraAuthTypes" type="conf:listOfStrings"/>
<anyAttribute namespace="##other" processContents="lax"/>
</complexType>
Version: @PACKAGE_VERSION@
Release: 1
Summary: Open source system for attribute-based Web SSO
-Group: System Environment/Libraries
+Group: Productivity/Networking/Security
Vendor: Internet2
License: Apache 2.0
URL: http://shibboleth.internet2.edu/
Source: %{name}-sp-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-root
PreReq: openssl, xmltooling-schemas, opensaml-schemas
-%if 0%{?suse_version} > 1030
+%if 0%{?suse_version} > 1030 && 0%{?suse_version} < 1130
PreReq: %{insserv_prereq}
BuildRequires: libXerces-c-devel >= 2.8.0
%else
%package devel
Summary: Shibboleth development Headers
-Group: Development/Libraries
+Group: Development/Libraries/C and C++
Requires: %{name} = %{version}-%{release}
-%if 0%{?suse_version} > 1030
+%if 0%{?suse_version} > 1030 && 0%{?suse_version} < 1130
Requires: libXerces-c-devel >= 2.8.0
%else
Requires: libxerces-c-devel >= 2.8.0
{
}
+#ifdef HAVE_GSSAPI
+GSSRequest::GSSRequest()
+{
+}
+
+GSSRequest::~GSSRequest()
+{
+}
+#endif
+
AbstractSPRequest::AbstractSPRequest(const char* category)
: m_sp(nullptr), m_mapper(nullptr), m_app(nullptr), m_sessionTried(false), m_session(nullptr),
m_log(&Category::getInstance(category)), m_parser(nullptr)
--- /dev/null
+/*
+ * Copyright 2010 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.
+ */
+
+/**
+ * @file shibsp/GSSRequest.h
+ *
+ * Interface to a GSS-authenticated request.
+ */
+
+#if !defined(__shibsp_gssreq_h__) && defined(HAVE_GSSAPI)
+#define __shibsp_gssreq_h__
+
+#include <shibsp/base.h>
+#include <xmltooling/io/GenericRequest.h>
+
+#ifdef HAVE_GSSGNU
+# include <gss.h>
+#elif defined HAVE_GSSMIT
+# include <gssapi/gssapi.h>
+# include <gssapi/gssapi_generic.h>
+#else
+# include <gssapi.h>
+#endif
+
+namespace shibsp {
+
+ /**
+ * Interface to a GSS-authenticated request.
+ */
+ class SHIBSP_API GSSRequest : public virtual xmltooling::GenericRequest
+ {
+ protected:
+ GSSRequest();
+ public:
+ virtual ~GSSRequest();
+
+ /**
+ * Returns the GSS-API context established for this request, or
+ * GSS_C_NO_CONTEXT if none is available.
+ *
+ * @return a GSS-API context handle, or GSS_C_NO_CONTEXT
+ */
+ virtual gss_ctx_id_t getGSSContext() const=0;
+ };
+};
+
+#endif /* __shibsp_gssreq_h__ */
base.h \
exceptions.h \
paths.h \
+ GSSRequest.h \
RequestMapper.h \
ServiceProvider.h \
SessionCache.h \
libshibsp_la_SOURCES = \
${common_sources} \
+ attribute/Base64AttributeDecoder.cpp \
attribute/DOMAttributeDecoder.cpp \
attribute/KeyInfoAttributeDecoder.cpp \
attribute/NameIDAttributeDecoder.cpp \
ServiceProvider::ServiceProvider()
{
+ m_authTypes.insert("shibboleth");
}
ServiceProvider::~ServiceProvider()
pair<bool,bool> requireSession = settings.first->getBool("requireSession");
pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");
- // If no session is required AND the AuthType (an Apache-derived concept) isn't shibboleth,
+ string lcAuthType;
+ if (authType.first) {
+ while (*authType.second)
+ lcAuthType += tolower(*authType.second++);
+ }
+
+ // If no session is required AND the AuthType (an Apache-derived concept) isn't recognized,
// then we ignore this request and consider it unprotected. Apache might lie to us if
// ShibBasicHijack is on, but that's up to it.
if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&
-#ifdef HAVE_STRCASECMP
- (!authType.first || strcasecmp(authType.second,"shibboleth")))
-#else
- (!authType.first || _stricmp(authType.second,"shibboleth")))
-#endif
- return make_pair(true,request.returnDecline());
+ (!authType.first || m_authTypes.find(lcAuthType) == m_authTypes.end()))
+ return make_pair(true, request.returnDecline());
// Fix for secadv 20050901
clearHeaders(request);
return initiator->run(request,false);
}
- request.setAuthType("shibboleth");
+ request.setAuthType(lcAuthType.c_str());
// We're done. Everything is okay. Nothing to report. Nothing to do..
// Let the caller decide how to proceed.
pair<bool,bool> requireSession = settings.first->getBool("requireSession");
pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");
- // If no session is required AND the AuthType (an Apache-derived concept) isn't shibboleth,
+ string lcAuthType;
+ if (authType.first) {
+ while (*authType.second)
+ lcAuthType += tolower(*authType.second++);
+ }
+
+ // If no session is required AND the AuthType (an Apache-derived concept) isn't recognized,
// then we ignore this request and consider it unprotected. Apache might lie to us if
// ShibBasicHijack is on, but that's up to it.
if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&
-#ifdef HAVE_STRCASECMP
- (!authType.first || strcasecmp(authType.second,"shibboleth")))
-#else
- (!authType.first || _stricmp(authType.second,"shibboleth")))
-#endif
- return make_pair(true,request.returnDecline());
+ (!authType.first || m_authTypes.find(lcAuthType) == m_authTypes.end()))
+ return make_pair(true, request.returnDecline());
// Do we have an access control plugin?
if (settings.second) {
#include <shibsp/util/PropertySet.h>
+#include <set>
#include <xmltooling/Lockable.h>
namespace xmltooling {
*/
virtual Remoted* lookupListener(const char* address) const;
+ protected:
+ /** The AuthTypes to "recognize" (defaults to "shibboleth"). */
+ std::set<std::string> m_authTypes;
+
private:
std::map<std::string,Remoted*> m_listenerMap;
};
SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory KeyInfoAttributeDecoderFactory;
SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory DOMAttributeDecoderFactory;
SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory XMLAttributeDecoderFactory;
+ SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory Base64AttributeDecoderFactory;
static const XMLCh _StringAttributeDecoder[] = UNICODE_LITERAL_22(S,t,r,i,n,g,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
static const XMLCh _ScopedAttributeDecoder[] = UNICODE_LITERAL_22(S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
static const XMLCh _KeyInfoAttributeDecoder[] =UNICODE_LITERAL_23(K,e,y,I,n,f,o,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
static const XMLCh _DOMAttributeDecoder[] = UNICODE_LITERAL_19(D,O,M,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
static const XMLCh _XMLAttributeDecoder[] = UNICODE_LITERAL_19(X,M,L,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
+ static const XMLCh _Base64AttributeDecoder[] = {
+ chLatin_B, chLatin_a, chLatin_s, chLatin_e, chDigit_6, chDigit_4,
+ chLatin_A, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
+ chLatin_D, chLatin_e, chLatin_c, chLatin_o, chLatin_d, chLatin_e, chLatin_r, chNull
+ };
static const XMLCh caseSensitive[] = UNICODE_LITERAL_13(c,a,s,e,S,e,n,s,i,t,i,v,e);
static const XMLCh hashAlg[] = UNICODE_LITERAL_7(h,a,s,h,A,l,g);
xmltooling::QName shibsp::KeyInfoAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _KeyInfoAttributeDecoder);
xmltooling::QName shibsp::DOMAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _DOMAttributeDecoder);
xmltooling::QName shibsp::XMLAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _XMLAttributeDecoder);
+xmltooling::QName shibsp::Base64AttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _Base64AttributeDecoder);
void shibsp::registerAttributeDecoders()
{
conf.AttributeDecoderManager.registerFactory(KeyInfoAttributeDecoderType, KeyInfoAttributeDecoderFactory);
conf.AttributeDecoderManager.registerFactory(DOMAttributeDecoderType, DOMAttributeDecoderFactory);
conf.AttributeDecoderManager.registerFactory(XMLAttributeDecoderType, XMLAttributeDecoderFactory);
+ conf.AttributeDecoderManager.registerFactory(Base64AttributeDecoderType, Base64AttributeDecoderFactory);
}
AttributeDecoder::AttributeDecoder(const DOMElement *e)
/** Decodes arbitrary XML into an XMLAttribute. */
extern SHIBSP_API xmltooling::QName XMLAttributeDecoderType;
+ /** Decodes base64-encoded data into a SimpleAttribute. */
+ extern SHIBSP_API xmltooling::QName Base64AttributeDecoderType;
+
/** Registers built-in AttributeDecoders into the runtime. */
void registerAttributeDecoders();
};
--- /dev/null
+/*
+ * Copyright 2010 The Danish CLARIN Consortium
+ *
+ * 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.
+ */
+
+/**
+ * Base64AttributeDecoder.cpp
+ *
+ * Decodes SAML containing base64-encoded values into SimpleAttributes.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+
+#include <xercesc/util/Base64.hpp>
+
+using namespace shibsp;
+using namespace opensaml::saml1;
+using namespace opensaml::saml2;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+ class SHIBSP_DLLLOCAL Base64AttributeDecoder : virtual public AttributeDecoder
+ {
+ public:
+ Base64AttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}
+ ~Base64AttributeDecoder() {}
+
+ shibsp::Attribute* decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=nullptr, const char* relyingParty=nullptr
+ ) const;
+ };
+
+ AttributeDecoder* SHIBSP_DLLLOCAL Base64AttributeDecoderFactory(const DOMElement* const & e)
+ {
+ return new Base64AttributeDecoder(e);
+ }
+};
+
+shibsp::Attribute* Base64AttributeDecoder::decode(
+ const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+ ) const
+{
+ auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));
+ vector<string>& dest = simple->getValues();
+ vector<XMLObject*>::const_iterator v,stop;
+
+ Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.Base64");
+
+ if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
+ const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
+ if (saml2attr) {
+ const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml2attr->getName());
+ log.debug(
+ "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu base64-encoded value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
+ if (saml1attr) {
+ const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+ v = values.begin();
+ stop = values.end();
+ if (log.isDebugEnabled()) {
+ auto_ptr_char n(saml1attr->getAttributeName());
+ log.debug(
+ "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu base64-encoded value(s)",
+ ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+ );
+ }
+ }
+ else {
+ log.warn("XMLObject type not recognized by Base64AttributeDecoder, no values returned");
+ return nullptr;
+ }
+ }
+
+ for (; v!=stop; ++v) {
+ if (!(*v)->hasChildren()) {
+ auto_ptr_char val((*v)->getTextContent());
+ if (val.get() && *val.get()) {
+ xsecsize_t x;
+ XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(val.get()),&x);
+ if (decoded) {
+ dest.push_back(reinterpret_cast<char*>(decoded));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+ XMLString::release(&decoded);
+#else
+ XMLString::release((char**)&decoded);
+#endif
+ }
+ else {
+ log.warn("skipping AttributeValue, unable to base64-decode");
+ }
+ }
+ else
+ log.warn("skipping empty AttributeValue");
+ }
+ else {
+ log.warn("skipping complex AttributeValue");
+ }
+ }
+
+ return dest.empty() ? nullptr : _decode(simple.release());
+ }
+
+ const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);
+ if (saml2name) {
+ if (log.isDebugEnabled()) {
+ auto_ptr_char f(saml2name->getFormat());
+ log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
+ }
+ auto_ptr_char val(saml2name->getName());
+ if (val.get() && *val.get()) {
+ xsecsize_t x;
+ XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(val.get()),&x);
+ if (decoded) {
+ dest.push_back(reinterpret_cast<char*>(decoded));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+ XMLString::release(&decoded);
+#else
+ XMLString::release((char**)&decoded);
+#endif
+ }
+ else {
+ log.warn("ignoring NameID, unable to base64-decode");
+ }
+ }
+ else
+ log.warn("ignoring empty NameID");
+ }
+ else {
+ const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
+ if (saml1name) {
+ if (log.isDebugEnabled()) {
+ auto_ptr_char f(saml1name->getFormat());
+ log.debug(
+ "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",
+ ids.front().c_str(), f.get() ? f.get() : "unspecified"
+ );
+ }
+ auto_ptr_char val(saml1name->getName());
+ if (val.get() && *val.get()) {
+ xsecsize_t x;
+ XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(val.get()),&x);
+ if (decoded) {
+ dest.push_back(reinterpret_cast<char*>(decoded));
+ #ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+ XMLString::release(&decoded);
+ #else
+ XMLString::release((char**)&decoded);
+ #endif
+ }
+ else {
+ log.warn("ignoring NameIdentifier, unable to base64-decode");
+ }
+ }
+ else
+ log.warn("ignoring empty NameIdentifier");
+ }
+ else {
+ log.warn("XMLObject type not recognized by Base64AttributeDecoder, no values returned");
+ return nullptr;
+ }
+ }
+
+ return dest.empty() ? nullptr : _decode(simple.release());
+}
// If no rules apply, remove the attribute entirely.
if (rulesToRun.empty()) {
m_log.warn(
- "no rule found, removing attribute (%s) from (%s)",
+ "no rule found, will remove attribute (%s) from (%s)",
attr->getId(), issuer.get() ? issuer.get() : "unknown source"
);
deletedAttributes[a] = true;
Attribute* attr = attributes[a];
if (deletedAttributes[a]) {
+ m_log.warn(
+ "removing filtered attribute (%s) from (%s)",
+ attr->getId(), issuer.get() ? issuer.get() : "unknown source"
+ );
delete attr;
deletedAttributes.erase(deletedAttributes.begin() + a);
attributes.erase(attributes.begin() + a);
attr->getId(), issuer.get() ? issuer.get() : "unknown source"
);
delete attr;
+ deletedAttributes.erase(deletedAttributes.begin() + a);
attributes.erase(attributes.begin() + a);
continue;
}
#include "Application.h"
#include "ServiceProvider.h"
#include "SessionCache.h"
-#include "attribute/Attribute.h"
+#include "attribute/SimpleAttribute.h"
#include "attribute/filtering/AttributeFilter.h"
#include "attribute/filtering/BasicFilteringContext.h"
#include "attribute/resolver/AttributeExtractor.h"
#include <saml/saml2/metadata/Metadata.h>
#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
#include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/URLEncoder.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
}
private:
- bool SAML1Query(QueryContext& ctx) const;
- bool SAML2Query(QueryContext& ctx) const;
+ void SAML1Query(QueryContext& ctx) const;
+ void SAML2Query(QueryContext& ctx) const;
Category& m_log;
string m_policyId;
bool m_subjectMatch;
vector<AttributeDesignator*> m_SAML1Designators;
vector<saml2::Attribute*> m_SAML2Designators;
+ vector<string> m_exceptionId;
};
AttributeResolver* SHIBSP_DLLLOCAL QueryResolverFactory(const DOMElement* const & e)
return new QueryResolver(e);
}
+ static const XMLCh exceptionId[] = UNICODE_LITERAL_11(e,x,c,e,p,t,i,o,n,I,d);
static const XMLCh policyId[] = UNICODE_LITERAL_8(p,o,l,i,c,y,I,d);
static const XMLCh subjectMatch[] = UNICODE_LITERAL_12(s,u,b,j,e,c,t,M,a,t,c,h);
};
}
child = XMLHelper::getNextSiblingElement(child);
}
+
+ string exid(XMLHelper::getAttrString(e, nullptr, exceptionId));
+ if (!exid.empty())
+ m_exceptionId.push_back(exid);
}
-bool QueryResolver::SAML1Query(QueryContext& ctx) const
+void QueryResolver::SAML1Query(QueryContext& ctx) const
{
#ifdef _DEBUG
xmltooling::NDC ndc("query");
find_if(ctx.getEntityDescriptor()->getAttributeAuthorityDescriptors(), isValidForProtocol(ctx.getProtocol()));
if (!AA) {
m_log.warn("no SAML 1.%d AttributeAuthority role found in metadata", version);
- return false;
+ return;
}
const Application& application = ctx.getApplication();
if (!response) {
m_log.error("unable to obtain a SAML response from attribute authority");
- return false;
+ throw BindingException("Unable to obtain a SAML response from attribute authority.");
}
else if (!response->getStatus() || !response->getStatus()->getStatusCode() || response->getStatus()->getStatusCode()->getValue()==nullptr ||
*(response->getStatus()->getStatusCode()->getValue()) != saml1p::StatusCode::SUCCESS) {
delete response;
m_log.error("attribute authority returned a SAML error");
- return true;
+ throw FatalProfileException("Attribute authority returned a SAML error.");
}
const vector<saml1::Assertion*>& assertions = const_cast<const saml1p::Response*>(response)->getAssertions();
if (assertions.empty()) {
delete response;
m_log.warn("response from attribute authority was empty");
- return true;
+ return;
}
- else if (assertions.size()>1)
+ else if (assertions.size()>1) {
m_log.warn("simple resolver only supports one assertion in the query response");
+ }
auto_ptr<saml1p::Response> wrapper(response);
saml1::Assertion* newtoken = assertions.front();
pair<bool,bool> signedAssertions = relyingParty->getBool("requireSignedAssertions");
if (!newtoken->getSignature() && signedAssertions.first && signedAssertions.second) {
m_log.error("assertion unsigned, rejecting it based on signedAssertions policy");
- return true;
+ throw SecurityPolicyException("Rejected unsigned assertion based on local policy.");
}
try {
}
catch (exception& ex) {
m_log.error("assertion failed policy validation: %s", ex.what());
- return true;
+ throw;
}
newtoken->detach();
m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what());
for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup<shibsp::Attribute>());
ctx.getResolvedAttributes().clear();
+ throw;
}
-
- return true;
}
-bool QueryResolver::SAML2Query(QueryContext& ctx) const
+void QueryResolver::SAML2Query(QueryContext& ctx) const
{
#ifdef _DEBUG
xmltooling::NDC ndc("query");
find_if(ctx.getEntityDescriptor()->getAttributeAuthorityDescriptors(), isValidForProtocol(samlconstants::SAML20P_NS));
if (!AA) {
m_log.warn("no SAML 2 AttributeAuthority role found in metadata");
- return false;
+ return;
}
const Application& application = ctx.getApplication();
if (!srt) {
m_log.error("unable to obtain a SAML response from attribute authority");
- return false;
+ throw BindingException("Unable to obtain a SAML response from attribute authority.");
}
auto_ptr<saml2p::StatusResponseType> wrapper(srt);
saml2p::Response* response = dynamic_cast<saml2p::Response*>(srt);
if (!response) {
m_log.error("message was not a samlp:Response");
- return true;
+ throw FatalProfileException("Attribute authority returned an unrecognized message.");
}
else if (!response->getStatus() || !response->getStatus()->getStatusCode() ||
!XMLString::equals(response->getStatus()->getStatusCode()->getValue(), saml2p::StatusCode::SUCCESS)) {
m_log.error("attribute authority returned a SAML error");
- return true;
+ throw FatalProfileException("Attribute authority returned a SAML error.");
}
saml2::Assertion* newtoken = nullptr;
const vector<saml2::EncryptedAssertion*>& encassertions = const_cast<const saml2p::Response*>(response)->getEncryptedAssertions();
if (encassertions.empty()) {
m_log.warn("response from attribute authority was empty");
- return true;
+ return;
}
else if (encassertions.size() > 1) {
m_log.warn("simple resolver only supports one assertion in the query response");
CredentialResolver* cr=application.getCredentialResolver();
if (!cr) {
m_log.warn("found encrypted assertion, but no CredentialResolver was available");
- return true;
+ throw FatalProfileException("Assertion was encrypted, but no decryption credentials are available.");
}
// Attempt to decrypt it.
tokenwrapper.release();
if (m_log.isDebugEnabled())
m_log.debugStream() << "decrypted Assertion: " << *newtoken << logging::eol;
+ // Free the Response now, so we know this is a stand-alone token later.
+ delete wrapper.release();
}
}
catch (exception& ex) {
m_log.error(ex.what());
- }
- if (newtoken) {
- // Free the Response now, so we know this is a stand-alone token later.
- delete wrapper.release();
- }
- else {
- // Nothing decrypted, should already be logged.
- return true;
+ throw;
}
}
else {
m_log.error("assertion unsigned, rejecting it based on signedAssertions policy");
if (!wrapper.get())
delete newtoken;
- return true;
+ throw SecurityPolicyException("Rejected unsigned assertion based on local policy.");
}
try {
m_log.warn("ignoring Assertion without NameID in Subject");
if (!wrapper.get())
delete newtoken;
- return true;
+ return;
}
}
}
m_log.error("assertion failed policy validation: %s", ex.what());
if (!wrapper.get())
delete newtoken;
- return true;
+ throw;
}
if (wrapper.get()) {
m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what());
for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup<shibsp::Attribute>());
ctx.getResolvedAttributes().clear();
+ throw;
}
-
- return true;
}
void QueryResolver::resolveAttributes(ResolutionContext& ctx) const
return;
}
- if (qctx.getNameID() && qctx.getEntityDescriptor()) {
- if (XMLString::equals(qctx.getProtocol(), samlconstants::SAML20P_NS)) {
- m_log.debug("attempting SAML 2.0 attribute query");
- SAML2Query(qctx);
- }
- else if (XMLString::equals(qctx.getProtocol(), samlconstants::SAML11_PROTOCOL_ENUM) ||
- XMLString::equals(qctx.getProtocol(), samlconstants::SAML10_PROTOCOL_ENUM)) {
- m_log.debug("attempting SAML 1.x attribute query");
- SAML1Query(qctx);
+ try {
+ if (qctx.getNameID() && qctx.getEntityDescriptor()) {
+ if (XMLString::equals(qctx.getProtocol(), samlconstants::SAML20P_NS)) {
+ m_log.debug("attempting SAML 2.0 attribute query");
+ SAML2Query(qctx);
+ }
+ else if (XMLString::equals(qctx.getProtocol(), samlconstants::SAML11_PROTOCOL_ENUM) ||
+ XMLString::equals(qctx.getProtocol(), samlconstants::SAML10_PROTOCOL_ENUM)) {
+ m_log.debug("attempting SAML 1.x attribute query");
+ SAML1Query(qctx);
+ }
+ else {
+ m_log.info("SSO protocol does not allow for attribute query");
+ }
}
else {
- m_log.info("SSO protocol does not allow for attribute query");
+ m_log.warn("can't attempt attribute query, either no NameID or no metadata to use");
}
}
- else {
- m_log.warn("can't attempt attribute query, either no NameID or no metadata to use");
+ catch (exception& ex) {
+ // Already logged.
+ if (!m_exceptionId.empty()) {
+ SimpleAttribute* attr = new SimpleAttribute(m_exceptionId);
+ attr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
+ qctx.getResolvedAttributes().push_back(attr);
+ }
}
}
#include "ServiceProvider.h"
#include "SessionCache.h"
#include "attribute/NameIDAttribute.h"
+#include "attribute/SimpleAttribute.h"
#include "attribute/filtering/AttributeFilter.h"
#include "attribute/filtering/BasicFilteringContext.h"
#include "attribute/resolver/AttributeExtractor.h"
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/security/TrustEngine.h>
#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/URLEncoder.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
}
private:
- bool doQuery(SimpleAggregationContext& ctx, const char* entityID, const NameID* name) const;
+ void doQuery(SimpleAggregationContext& ctx, const char* entityID, const NameID* name) const;
Category& m_log;
string m_policyId;
TrustEngine* m_trust;
vector<saml2::Attribute*> m_designators;
vector< pair<string,bool> > m_sources;
+ vector<string> m_exceptionId;
};
AttributeResolver* SHIBSP_DLLLOCAL SimpleAggregationResolverFactory(const DOMElement* const & e)
static const XMLCh attributeId[] = UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,d);
static const XMLCh Entity[] = UNICODE_LITERAL_6(E,n,t,i,t,y);
static const XMLCh EntityReference[] = UNICODE_LITERAL_15(E,n,t,i,t,y,R,e,f,e,r,e,n,c,e);
+ static const XMLCh exceptionId[] = UNICODE_LITERAL_11(e,x,c,e,p,t,i,o,n,I,d);
static const XMLCh format[] = UNICODE_LITERAL_6(f,o,r,m,a,t);
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 policyId[] = UNICODE_LITERAL_8(p,o,l,i,c,y,I,d);
m_format = aid;
}
+ string exid(XMLHelper::getAttrString(e, nullptr, exceptionId));
+ if (!exid.empty())
+ m_exceptionId.push_back(exid);
+
DOMElement* child = XMLHelper::getFirstChildElement(e, _MetadataProvider);
if (child) {
string t(XMLHelper::getAttrString(child, nullptr, _type));
}
}
-bool SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const char* entityID, const NameID* name) const
+void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const char* entityID, const NameID* name) const
{
#ifdef _DEBUG
xmltooling::NDC ndc("doQuery");
(m_metadata ? m_metadata : application.getMetadataProvider())->getEntityDescriptor(mc);
if (!mdresult.first) {
m_log.warn("unable to locate metadata for provider (%s)", entityID);
- return false;
+ return;
}
else if (!(AA=dynamic_cast<const AttributeAuthorityDescriptor*>(mdresult.second))) {
m_log.warn("no SAML 2 AttributeAuthority role found in metadata for (%s)", entityID);
- return false;
+ return;
}
const PropertySet* relyingParty = application.getRelyingParty(mdresult.first);
if (!srt) {
m_log.error("unable to obtain a SAML response from attribute authority (%s)", entityID);
- return false;
+ throw BindingException("Unable to obtain a SAML response from attribute authority.");
}
auto_ptr<saml2p::StatusResponseType> wrapper(srt);
saml2p::Response* response = dynamic_cast<saml2p::Response*>(srt);
if (!response) {
m_log.error("message was not a samlp:Response");
- return true;
+ throw FatalProfileException("Attribute authority returned an unrecognized message.");
}
else if (!response->getStatus() || !response->getStatus()->getStatusCode() ||
!XMLString::equals(response->getStatus()->getStatusCode()->getValue(), saml2p::StatusCode::SUCCESS)) {
m_log.error("attribute authority (%s) returned a SAML error", entityID);
- return true;
+ throw FatalProfileException("Attribute authority returned a SAML error.");
}
saml2::Assertion* newtoken = nullptr;
const_cast<const saml2p::Response*>(response)->getEncryptedAssertions();
if (encassertions.empty()) {
m_log.warn("response from attribute authority was empty");
- return true;
+ return;
}
else if (encassertions.size() > 1) {
m_log.warn("simple resolver only supports one assertion in the query response");
CredentialResolver* cr=application.getCredentialResolver();
if (!cr) {
m_log.warn("found encrypted assertion, but no CredentialResolver was available");
- return true;
+ throw FatalProfileException("Assertion was encrypted, but no decryption credentials are available.");
}
// Attempt to decrypt it.
tokenwrapper.release();
if (m_log.isDebugEnabled())
m_log.debugStream() << "decrypted Assertion: " << *newtoken << logging::eol;
+ // Free the Response now, so we know this is a stand-alone token later.
+ delete wrapper.release();
}
}
catch (exception& ex) {
m_log.error(ex.what());
- }
- if (newtoken) {
- // Free the Response now, so we know this is a stand-alone token later.
- delete wrapper.release();
- }
- else {
- // Nothing decrypted, should already be logged.
- return true;
+ throw;
}
}
else {
m_log.error("assertion unsigned, rejecting it based on signedAssertions policy");
if (!wrapper.get())
delete newtoken;
- return true;
+ throw SecurityPolicyException("Rejected unsigned assertion based on local policy.");
}
try {
m_log.warn("ignoring Assertion without NameID in Subject");
if (!wrapper.get())
delete newtoken;
- return true;
+ return;
}
}
}
m_log.error("assertion failed policy validation: %s", ex.what());
if (!wrapper.get())
delete newtoken;
- return true;
+ throw;
}
if (wrapper.get()) {
m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what());
for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup<shibsp::Attribute>());
ctx.getResolvedAttributes().clear();
+ throw;
}
-
- return true;
}
void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
if (qctx.getEntityID())
history.insert(qctx.getEntityID());
+ // Prepare to track exceptions.
+ SimpleAttribute* exceptAttr = nullptr;
+ if (!m_exceptionId.empty()) {
+ exceptAttr = new SimpleAttribute(m_exceptionId);
+ }
+ auto_ptr<Attribute> exceptWrapper(exceptAttr);
+
// We have a master loop over all the possible sources of material.
for (vector< pair<string,bool> >::const_iterator source = m_sources.begin(); source != m_sources.end(); ++source) {
if (source->second) {
// A literal entityID to query.
if (history.count(source->first) == 0) {
m_log.debug("issuing SAML query to (%s)", source->first.c_str());
- doQuery(qctx, source->first.c_str(), n ? n : qctx.getNameID());
+ try {
+ doQuery(qctx, source->first.c_str(), n ? n : qctx.getNameID());
+ }
+ catch (exception& ex) {
+ if (exceptAttr)
+ exceptAttr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
+ }
history.insert(source->first);
}
else {
for (vector<string>::const_iterator link = links.begin(); link != links.end(); ++link) {
if (history.count(*link) == 0) {
m_log.debug("issuing SAML query to (%s)", link->c_str());
- doQuery(qctx, link->c_str(), n ? n : qctx.getNameID());
+ try {
+ doQuery(qctx, link->c_str(), n ? n : qctx.getNameID());
+ }
+ catch (exception& ex) {
+ if (exceptAttr)
+ exceptAttr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
+ }
history.insert(*link);
}
else {
for (vector<string>::const_iterator link = links.begin(); link != links.end(); ++link) {
if (history.count(*link) == 0) {
m_log.debug("issuing SAML query to (%s)", link->c_str());
- doQuery(qctx, link->c_str(), n ? n : qctx.getNameID());
+ try {
+ doQuery(qctx, link->c_str(), n ? n : qctx.getNameID());
+ }
+ catch (exception& ex) {
+ if (exceptAttr)
+ exceptAttr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
+ }
history.insert(*link);
}
else {
}
}
}
+
+ if (exceptAttr) {
+ qctx.getResolvedAttributes().push_back(exceptWrapper.release());
+ }
}
#include <shibsp/handler/Handler.h>
#include <shibsp/remoting/ListenerService.h>
+#include <set>
+
namespace xmltooling {
class XMLTOOL_API HTTPRequest;
class XMLTOOL_API HTTPResponse;
*/
class SHIBSP_API RemotedHandler : public virtual Handler, public Remoted
{
+ static std::set<std::string> m_remotedHeaders;
+
public:
virtual ~RemotedHandler();
+ /**
+ * Ensures that a request header will be remoted.
+ *
+ * @param header name of request header to remote
+ */
+ static void addRemotedHeader(const char* header);
+
protected:
RemotedHandler();
* to remote the request information.
*
* @param request an SPRequest to remote
- * @param headers array of request headers to copy to remote request
+ * @param headers array of additional request headers to copy to remote request
* @param certs true iff client certificates should be available for the remote request
* @return the input dataflow object
*/
delete m_org;
delete m_entityAttrs;
for_each(m_contacts.begin(), m_contacts.end(), xmltooling::cleanup<ContactPerson>());
+ for_each(m_formats.begin(), m_formats.end(), xmltooling::cleanup<NameIDFormat>());
for_each(m_reqAttrs.begin(), m_reqAttrs.end(), xmltooling::cleanup<RequestedAttribute>());
for_each(m_attrConsumers.begin(), m_attrConsumers.end(), xmltooling::cleanup<AttributeConsumingService>());
#endif
Organization* m_org;
EntityAttributes* m_entityAttrs;
vector<ContactPerson*> m_contacts;
+ vector<NameIDFormat*> m_formats;
vector<RequestedAttribute*> m_reqAttrs;
vector<AttributeConsumingService*> m_attrConsumers;
#endif
m_contacts.push_back(cp);
}
else {
- RequestedAttribute* req = dynamic_cast<RequestedAttribute*>(child.get());
- if (req) {
+ NameIDFormat* nif = dynamic_cast<NameIDFormat*>(child.get());
+ if (nif) {
child.release();
- m_reqAttrs.push_back(req);
+ m_formats.push_back(nif);
}
else {
- AttributeConsumingService* acs = dynamic_cast<AttributeConsumingService*>(child.get());
- if (acs) {
+ RequestedAttribute* req = dynamic_cast<RequestedAttribute*>(child.get());
+ if (req) {
child.release();
- m_attrConsumers.push_back(acs);
+ m_reqAttrs.push_back(req);
}
else {
- UIInfo* info = dynamic_cast<UIInfo*>(child.get());
- if (info) {
- if (!m_uiinfo) {
- child.release();
- m_uiinfo = info;
- }
- else {
- m_log.warn("skipping duplicate UIInfo element");
- }
+ AttributeConsumingService* acs = dynamic_cast<AttributeConsumingService*>(child.get());
+ if (acs) {
+ child.release();
+ m_attrConsumers.push_back(acs);
}
else {
- Organization* org = dynamic_cast<Organization*>(child.get());
- if (org) {
- if (!m_org) {
+ UIInfo* info = dynamic_cast<UIInfo*>(child.get());
+ if (info) {
+ if (!m_uiinfo) {
child.release();
- m_org = org;
+ m_uiinfo = info;
}
else {
- m_log.warn("skipping duplicate Organization element");
+ m_log.warn("skipping duplicate UIInfo element");
}
}
else {
- EntityAttributes* ea = dynamic_cast<EntityAttributes*>(child.get());
- if (ea) {
- if (!m_entityAttrs) {
+ Organization* org = dynamic_cast<Organization*>(child.get());
+ if (org) {
+ if (!m_org) {
child.release();
- m_entityAttrs = ea;
+ m_org = org;
}
else {
- m_log.warn("skipping duplicate EntityAttributes element");
+ m_log.warn("skipping duplicate Organization element");
+ }
+ }
+ else {
+ EntityAttributes* ea = dynamic_cast<EntityAttributes*>(child.get());
+ if (ea) {
+ if (!m_entityAttrs) {
+ child.release();
+ m_entityAttrs = ea;
+ }
+ else {
+ m_log.warn("skipping duplicate EntityAttributes element");
+ }
}
}
}
entity->setOrganization(m_org->cloneOrganization());
for (vector<ContactPerson*>::const_iterator cp = m_contacts.begin(); cp != m_contacts.end(); ++cp)
- entity->getContactPersons().push_back((*cp)->cloneContactPerson());
+ entity->getContactPersons().push_back((*cp)->cloneContactPerson());
if (m_entityAttrs) {
if (!entity->getExtensions())
role = entity->getSPSSODescriptors().front();
}
+ for (vector<NameIDFormat*>::const_iterator nif = m_formats.begin(); nif != m_formats.end(); ++nif)
+ role->getNameIDFormats().push_back((*nif)->cloneNameIDFormat());
+
if (m_uiinfo) {
if (!role->getExtensions())
role->setExtensions(ExtensionsBuilder::buildExtensions());
*/
#include "internal.h"
-#include "Application.h"
#include "exceptions.h"
+#include "Application.h"
+#include "GSSRequest.h"
#include "ServiceProvider.h"
#include "SPRequest.h"
#include "handler/RemotedHandler.h"
#include <algorithm>
#include <xmltooling/unicode.h>
+#include <xercesc/util/Base64.hpp>
#ifndef SHIBSP_LITE
# include "util/CGIParser.h"
#ifndef SHIBSP_LITE
namespace shibsp {
- class SHIBSP_DLLLOCAL RemotedRequest : public virtual HTTPRequest
+ class SHIBSP_DLLLOCAL RemotedRequest :
+#ifdef HAVE_GSSAPI
+ public GSSRequest,
+#endif
+ public HTTPRequest
{
DDF& m_input;
mutable CGIParser* m_parser;
mutable vector<XSECCryptoX509*> m_certs;
+#ifdef HAVE_GSSAPI
+ mutable gss_ctx_id_t m_gss;
+#endif
public:
- RemotedRequest(DDF& input) : m_input(input), m_parser(nullptr) {}
+ RemotedRequest(DDF& input) : m_input(input), m_parser(nullptr)
+#ifdef HAVE_GSSAPI
+ , m_gss(GSS_C_NO_CONTEXT)
+#endif
+ {
+ }
+
virtual ~RemotedRequest() {
for_each(m_certs.begin(), m_certs.end(), xmltooling::cleanup<XSECCryptoX509>());
delete m_parser;
+#ifdef HAVE_GSSAPI
+ if (m_gss != GSS_C_NO_CONTEXT) {
+ OM_uint32 minor;
+ gss_delete_sec_context(&minor, &m_gss, GSS_C_NO_BUFFER);
+ }
+#endif
}
// GenericRequest
const char* getScheme() const {
return m_input["scheme"].string();
}
+ bool isSecure() const {
+ return HTTPRequest::isSecure();
+ }
const char* getHostname() const {
return m_input["hostname"].string();
}
const std::vector<XSECCryptoX509*>& getClientCertificates() const;
+#ifdef HAVE_GSSAPI
+ // GSSRequest
+ gss_ctx_id_t getGSSContext() const;
+#endif
+
// HTTPRequest
const char* getMethod() const {
return m_input["method"].string();
return m_certs;
}
+#ifdef HAVE_GSSAPI
+gss_ctx_id_t RemotedRequest::getGSSContext() const
+{
+ if (m_gss == GSS_C_NO_CONTEXT) {
+ const char* encoded = m_input["gss_context"].string();
+ if (encoded) {
+ xsecsize_t x;
+ XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(encoded), &x);
+ if (decoded) {
+ gss_buffer_desc importbuf;
+ importbuf.length = x;
+ importbuf.value = decoded;
+ OM_uint32 minor;
+ OM_uint32 major = gss_import_sec_context(&minor, &importbuf, &m_gss);
+ if (major != GSS_S_COMPLETE)
+ m_gss = GSS_C_NO_CONTEXT;
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+ XMLString::release(&decoded);
+#else
+ XMLString::release((char**)&decoded);
+#endif
+ }
+ }
+ }
+ return m_gss;
+}
+#endif
+
long RemotedResponse::sendResponse(std::istream& in, long status)
{
string msg;
}
}
+set<string> RemotedHandler::m_remotedHeaders;
+
RemotedHandler::RemotedHandler()
{
}
listener->unregListener(m_address.c_str(),this);
}
+void RemotedHandler::addRemotedHeader(const char* header)
+{
+ m_remotedHeaders.insert(header);
+}
+
DDF RemotedHandler::wrap(const SPRequest& request, const vector<string>* headers, bool certs) const
{
DDF in = DDF(m_address.c_str()).structure();
in.addmember("url").unsafe_string(request.getRequestURL());
in.addmember("query").string(request.getQueryString());
- if (headers) {
+ if (headers || !m_remotedHeaders.empty()) {
string hdr;
DDF hin = in.addmember("headers").structure();
- for (vector<string>::const_iterator h = headers->begin(); h!=headers->end(); ++h) {
- hdr = request.getHeader(h->c_str());
+ if (headers) {
+ for (vector<string>::const_iterator h = headers->begin(); h!=headers->end(); ++h) {
+ hdr = request.getHeader(h->c_str());
+ if (!hdr.empty())
+ hin.addmember(h->c_str()).unsafe_string(hdr.c_str());
+ }
+ }
+ for (set<string>::const_iterator hh = m_remotedHeaders.begin(); hh != m_remotedHeaders.end(); ++hh) {
+ hdr = request.getHeader(hh->c_str());
if (!hdr.empty())
- hin.addmember(h->c_str()).unsafe_string(hdr.c_str());
+ hin.addmember(hh->c_str()).unsafe_string(hdr.c_str());
}
}
#endif
}
+#ifdef HAVE_GSSAPI
+ const GSSRequest* gss = dynamic_cast<const GSSRequest*>(&request);
+ if (gss) {
+ gss_ctx_id_t ctx = gss->getGSSContext();
+ if (ctx != GSS_C_NO_CONTEXT) {
+ OM_uint32 minor;
+ gss_buffer_desc contextbuf;
+ contextbuf.length = 0;
+ contextbuf.value = nullptr;
+ OM_uint32 major = gss_export_sec_context(&minor, &ctx, &contextbuf);
+ if (major == GSS_S_COMPLETE) {
+ xsecsize_t len=0;
+ XMLByte* out=Base64::encode(reinterpret_cast<const XMLByte*>(contextbuf.value), contextbuf.length, &len);
+ if (out) {
+ string ctx;
+ ctx.append(reinterpret_cast<char*>(out), len);
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+ XMLString::release(&out);
+#else
+ XMLString::release((char**)&out);
+#endif
+ in.addmember("gss_context").string(ctx.c_str());
+ }
+ else {
+ request.log(SPRequest::SPError, "error while base64-encoding GSS context");
+ }
+ }
+ else {
+ request.log(SPRequest::SPError, "error while exporting GSS context");
+ }
+ }
+ }
+#endif
+
return in;
}
#include "handler/RemotedHandler.h"
#include "util/CGIParser.h"
+#include <xmltooling/version.h>
+#include <xmltooling/util/DateTime.h>
+
+#ifdef HAVE_SYS_UTSNAME_H
+# include <sys/utsname.h>
+#endif
+
using namespace shibsp;
#ifndef SHIBSP_LITE
# include "SessionCache.h"
private:
pair<bool,long> processMessage(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
+ ostream& systemInfo(ostream& os) const;
set<string> m_acl;
};
map<string,const char*> props;
settings.first->getAll(props);
+ DateTime now(time(nullptr));
+ now.parseDateTime();
+ auto_ptr_char timestamp(now.getFormattedString());
request.setContentType("text/xml");
stringstream msg;
- msg << "<StatusHandler>";
+ msg << "<StatusHandler time='" << timestamp.get() << "'>";
msg << "<Version Xerces-C='" << XERCES_FULLVERSIONDOT
+ << "' XML-Tooling-C='" << XMLTOOLING_FULLVERSIONDOT
#ifndef SHIBSP_LITE
<< "' XML-Security-C='" << XSEC_FULLVERSIONDOT
<< "' OpenSAML-C='" << OPENSAML_FULLVERSIONDOT
#endif
<< "' Shibboleth='" << PACKAGE_VERSION << "'/>";
- msg << "<RequestSettings";
+ systemInfo(msg) << "<RequestSettings";
for (map<string,const char*>::const_iterator p = props.begin(); p != props.end(); ++p)
msg << ' ' << p->first << "='" << p->second << "'";
msg << '>' << target << "</RequestSettings>";
}
catch (XMLToolingException& ex) {
m_log.error("error while processing request: %s", ex.what());
+ DateTime now(time(nullptr));
+ now.parseDateTime();
+ auto_ptr_char timestamp(now.getFormattedString());
request.setContentType("text/xml");
stringstream msg;
- msg << "<StatusHandler>";
+ msg << "<StatusHandler time='" << timestamp.get() << "'>";
msg << "<Version Xerces-C='" << XERCES_FULLVERSIONDOT
+ << "' XML-Tooling-C='" << XMLTOOLING_FULLVERSIONDOT
#ifndef SHIBSP_LITE
<< "' XML-Security-C='" << XSEC_FULLVERSIONDOT
<< "' OpenSAML-C='" << OPENSAML_FULLVERSIONDOT
#endif
<< "' Shibboleth='" << PACKAGE_VERSION << "'/>";
- msg << "<Status><Exception type='" << ex.getClassName() << "'>" << ex.what() << "</Exception></Status>";
+ systemInfo(msg) << "<Status><Exception type='" << ex.getClassName() << "'>" << ex.what() << "</Exception></Status>";
msg << "</StatusHandler>";
return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
}
catch (exception& ex) {
m_log.error("error while processing request: %s", ex.what());
+ DateTime now(time(nullptr));
+ now.parseDateTime();
+ auto_ptr_char timestamp(now.getFormattedString());
request.setContentType("text/xml");
stringstream msg;
- msg << "<StatusHandler>";
+ msg << "<StatusHandler time='" << timestamp.get() << "'>";
msg << "<Version Xerces-C='" << XERCES_FULLVERSIONDOT
+ << "' XML-Tooling-C='" << XMLTOOLING_FULLVERSIONDOT
#ifndef SHIBSP_LITE
<< "' XML-Security-C='" << XSEC_FULLVERSIONDOT
<< "' OpenSAML-C='" << OPENSAML_FULLVERSIONDOT
#endif
<< "' Shibboleth='" << PACKAGE_VERSION << "'/>";
- msg << "<Status><Exception type='std::exception'>" << ex.what() << "</Exception></Status>";
+ systemInfo(msg) << "<Status><Exception type='std::exception'>" << ex.what() << "</Exception></Status>";
msg << "</StatusHandler>";
return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
}
#ifndef SHIBSP_LITE
m_log.debug("processing status request");
+ DateTime now(time(nullptr));
+ now.parseDateTime();
+ auto_ptr_char timestamp(now.getFormattedString());
+
stringstream s;
- s << "<StatusHandler>";
+ s << "<StatusHandler time='" << timestamp.get() << "'>";
const char* status = "<OK/>";
s << "<Version Xerces-C='" << XERCES_FULLVERSIONDOT
+ << "' XML-Tooling-C='" << XMLTOOLING_FULLVERSIONDOT
<< "' XML-Security-C='" << XSEC_FULLVERSIONDOT
<< "' OpenSAML-C='" << OPENSAML_FULLVERSIONDOT
<< "' Shibboleth='" << PACKAGE_VERSION << "'/>";
+ systemInfo(s);
+
const char* param = nullptr;
if (param) {
}
return make_pair(false,0L);
#endif
}
+
+#ifdef WIN32
+typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
+#endif
+
+ostream& StatusHandler::systemInfo(ostream& os) const
+{
+#if defined(HAVE_SYS_UTSNAME_H)
+ struct utsname sysinfo;
+ if (uname(&sysinfo) == 0) {
+ os << "<NonWindows";
+ if (*sysinfo.sysname)
+ os << " sysname='" << sysinfo.sysname << "'";
+ if (*sysinfo.nodename)
+ os << " nodename='" << sysinfo.nodename << "'";
+ if (*sysinfo.release)
+ os << " release='" << sysinfo.release << "'";
+ if (*sysinfo.version)
+ os << " version='" << sysinfo.version << "'";
+ if (*sysinfo.machine)
+ os << " machine='" << sysinfo.machine << "'";
+ os << "/>";
+ }
+#elif defined(WIN32)
+ OSVERSIONINFOEX osvi;
+ memset(&osvi, 0, sizeof(OSVERSIONINFOEX));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ if(GetVersionEx((OSVERSIONINFO*)&osvi)) {
+ os << "<Windows"
+ << " version='" << osvi.dwMajorVersion << "." << osvi.dwMinorVersion << "'"
+ << " build='" << osvi.dwBuildNumber << "'";
+ if (osvi.wServicePackMajor > 0)
+ os << " servicepack='" << osvi.wServicePackMajor << "." << osvi.wServicePackMinor << "'";
+ switch (osvi.wProductType) {
+ case VER_NT_WORKSTATION:
+ os << " producttype='Workstation'";
+ break;
+ case VER_NT_SERVER:
+ case VER_NT_DOMAIN_CONTROLLER:
+ os << " producttype='Server'";
+ break;
+ }
+
+ SYSTEM_INFO si;
+ memset(&si, 0, sizeof(SYSTEM_INFO));
+ PGNSI pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
+ if(pGNSI)
+ pGNSI(&si);
+ else
+ GetSystemInfo(&si);
+ switch (si.dwProcessorType) {
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ os << " arch='i386'";
+ break;
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ os << " arch='x86_64'";
+ break;
+ case PROCESSOR_ARCHITECTURE_IA64:
+ os << " arch='IA64'";
+ break;
+ }
+ os << " cpucount='" << si.dwNumberOfProcessors << "'";
+
+ MEMORYSTATUSEX ms;
+ memset(&ms, 0, sizeof(MEMORYSTATUSEX));
+ ms.dwLength = sizeof(MEMORYSTATUSEX);
+ if (GlobalMemoryStatusEx(&ms)) {
+ os << " memory='" << (ms.ullTotalPhys / (1024 * 1024)) << "M'";
+ }
+
+ os << "/>";
+ }
+#endif
+ return os;
+}
#include "SessionCacheEx.h"
#include "TransactionLog.h"
#include "attribute/Attribute.h"
+#include "handler/RemotedHandler.h"
#include "remoting/ListenerService.h"
#include "util/SPConstants.h"
);
bool matches(
const Application& app,
- const xmltooling::HTTPRequest& request,
+ const HTTPRequest& request,
const saml2md::EntityDescriptor* issuer,
const saml2::NameID& nameid,
const set<string>* indexes
void remove(const Application& app, const char* key);
void test();
- string active(const Application& app, const xmltooling::HTTPRequest& request) {
+ string active(const Application& app, const HTTPRequest& request) {
+ if (!m_inboundHeader.empty()) {
+ string session_id = request.getHeader(m_inboundHeader.c_str());
+ if (!session_id.empty())
+ return session_id;
+ }
pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
const char* session_id = request.getCookie(shib_cookie.first.c_str());
return (session_id ? session_id : "");
return nullptr;
}
- Session* find(const Application& app, HTTPRequest& request, const char* client_addr=nullptr, time_t* timeout=nullptr) {
- string id = active(app, request);
- if (id.empty())
- return nullptr;
- try {
- Session* session = find(app, id.c_str(), client_addr, timeout);
- if (session)
- return session;
- HTTPResponse* response = dynamic_cast<HTTPResponse*>(&request);
- if (response) {
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
- string exp(shib_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response->setCookie(shib_cookie.first.c_str(), exp.c_str());
- }
- }
- catch (exception&) {
- HTTPResponse* response = dynamic_cast<HTTPResponse*>(&request);
- if (response) {
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
- string exp(shib_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response->setCookie(shib_cookie.first.c_str(), exp.c_str());
- }
- throw;
- }
- return nullptr;
- }
-
- void remove(const Application& app, const HTTPRequest& request, HTTPResponse* response=nullptr) {
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
- const char* session_id = request.getCookie(shib_cookie.first.c_str());
- if (session_id && *session_id) {
- if (response) {
- string exp(shib_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response->setCookie(shib_cookie.first.c_str(), exp.c_str());
- }
- remove(app, session_id);
- }
- }
+ Session* find(const Application& app, HTTPRequest& request, const char* client_addr=nullptr, time_t* timeout=nullptr);
+ void remove(const Application& app, const HTTPRequest& request, HTTPResponse* response=nullptr);
unsigned long getCacheTimeout(const Application& app) {
// Computes offset for adjusting expiration of sessions.
#endif
const DOMElement* m_root; // Only valid during initialization
unsigned long m_inprocTimeout,m_cacheTimeout,m_cacheAllowance;
+ string m_inboundHeader,m_outboundHeader;
// inproc means we buffer sessions in memory
RWLock* m_lock;
static const XMLCh cacheAssertions[] = UNICODE_LITERAL_15(c,a,c,h,e,A,s,s,e,r,t,i,o,n,s);
static const XMLCh cacheTimeout[] = UNICODE_LITERAL_12(c,a,c,h,e,T,i,m,e,o,u,t);
static const XMLCh inprocTimeout[] = UNICODE_LITERAL_13(i,n,p,r,o,c,T,i,m,e,o,u,t);
+ static const XMLCh inboundHeader[] = UNICODE_LITERAL_13(i,n,b,o,u,n,d,H,e,a,d,e,r);
+ static const XMLCh outboundHeader[] = UNICODE_LITERAL_14(o,u,t,b,o,u,n,d,H,e,a,d,e,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 _StorageServiceLite[] = UNICODE_LITERAL_18(S,t,o,r,a,g,e,S,e,r,v,i,c,e,L,i,t,e);
m_cacheAllowance = XMLHelper::getAttrInt(e, 0, cacheAllowance);
if (inproc)
m_inprocTimeout = XMLHelper::getAttrInt(e, 900, inprocTimeout);
+ m_inboundHeader = XMLHelper::getAttrString(e, nullptr, inboundHeader);
+ if (!m_inboundHeader.empty())
+ RemotedHandler::addRemotedHeader(m_inboundHeader.c_str());
+ m_outboundHeader = XMLHelper::getAttrString(e, nullptr, outboundHeader);
#ifndef SHIBSP_LITE
if (conf.isEnabled(SPConfig::OutOfProcess)) {
xlog->log.info("}");
}
+ if (!m_outboundHeader.empty())
+ httpResponse.setResponseHeader(m_outboundHeader.c_str(), key.get());
+
time_t cookieLifetime = 0;
pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_", &cookieLifetime);
string k(key.get());
return session;
}
+Session* SSCache::find(const Application& app, HTTPRequest& request, const char* client_addr, time_t* timeout)
+{
+ string id = active(app, request);
+ if (id.empty())
+ return nullptr;
+ try {
+ Session* session = find(app, id.c_str(), client_addr, timeout);
+ if (session)
+ return session;
+ HTTPResponse* response = dynamic_cast<HTTPResponse*>(&request);
+ if (response) {
+ if (!m_outboundHeader.empty())
+ response->setResponseHeader(m_outboundHeader.c_str(), nullptr);
+ pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
+ string exp(shib_cookie.second);
+ exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
+ response->setCookie(shib_cookie.first.c_str(), exp.c_str());
+ }
+ }
+ catch (exception&) {
+ HTTPResponse* response = dynamic_cast<HTTPResponse*>(&request);
+ if (response) {
+ if (!m_outboundHeader.empty())
+ response->setResponseHeader(m_outboundHeader.c_str(), nullptr);
+ pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
+ string exp(shib_cookie.second);
+ exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
+ response->setCookie(shib_cookie.first.c_str(), exp.c_str());
+ }
+ throw;
+ }
+ return nullptr;
+}
+
+void SSCache::remove(const Application& app, const HTTPRequest& request, HTTPResponse* response)
+{
+ string session_id;
+ pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
+
+ if (!m_inboundHeader.empty())
+ session_id = request.getHeader(m_inboundHeader.c_str());
+ if (session_id.empty()) {
+ const char* c = request.getCookie(shib_cookie.first.c_str());
+ if (c && *c)
+ session_id = c;
+ }
+
+ if (!session_id.empty()) {
+ if (response) {
+ if (!m_outboundHeader.empty())
+ response->setResponseHeader(m_outboundHeader.c_str(), nullptr);
+ string exp(shib_cookie.second);
+ exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
+ response->setCookie(shib_cookie.first.c_str(), exp.c_str());
+ }
+ remove(app, session_id.c_str());
+ }
+}
+
void SSCache::remove(const Application& app, const char* key)
{
#ifdef _DEBUG
#ifdef _DEBUG
xmltooling::NDC ndc("XMLRequestMapperImpl");
#endif
- static const XMLCh _default[] = UNICODE_LITERAL_7(d,e,f,a,u,l,t);
- static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);
static const XMLCh _RequestMap[] = UNICODE_LITERAL_10(R,e,q,u,e,s,t,M,a,p);
if (e && !XMLHelper::isNodeNamed(e, SHIB2SPCONFIG_NS, _RequestMap))
class SHIBSP_DLLLOCAL XMLConfigImpl : public DOMPropertySet, public DOMNodeFilter
{
public:
- XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log);
+ XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, Category& log);
~XMLConfigImpl();
RequestMapper* m_requestMapper;
}
private:
- void doExtensions(const DOMElement* e, const char* label, Category& log);
- void doListener(const DOMElement* e, Category& log);
- void doCaching(const DOMElement* e, Category& log);
+ void doExtensions(const DOMElement*, const char*, Category&);
+ void doListener(const DOMElement*, XMLConfig*, Category&);
+ void doCaching(const DOMElement*, XMLConfig*, Category&);
void cleanup();
- const XMLConfig* m_outer;
DOMDocument* m_document;
};
private:
friend class XMLConfigImpl;
XMLConfigImpl* m_impl;
- mutable ListenerService* m_listener;
- mutable SessionCache* m_sessionCache;
+ ListenerService* m_listener;
+ SessionCache* m_sessionCache;
#ifndef SHIBSP_LITE
- mutable TransactionLog* m_tranLog;
- mutable map<string,StorageService*> m_storage;
+ TransactionLog* m_tranLog;
+ map<string,StorageService*> m_storage;
#endif
};
}
}
-void XMLConfigImpl::doListener(const DOMElement* e, Category& log)
+void XMLConfigImpl::doListener(const DOMElement* e, XMLConfig* conf, Category& log)
{
#ifdef WIN32
string plugtype(TCP_LISTENER_SERVICE);
}
log.info("building ListenerService of type %s...", plugtype.c_str());
- m_outer->m_listener = SPConfig::getConfig().ListenerServiceManager.newPlugin(plugtype.c_str(), child);
+ conf->m_listener = SPConfig::getConfig().ListenerServiceManager.newPlugin(plugtype.c_str(), child);
}
-void XMLConfigImpl::doCaching(const DOMElement* e, Category& log)
+void XMLConfigImpl::doCaching(const DOMElement* e, XMLConfig* conf, Category& log)
{
- SPConfig& conf = SPConfig::getConfig();
+ SPConfig& spConf = SPConfig::getConfig();
#ifndef SHIBSP_LITE
SAMLConfig& samlConf = SAMLConfig::getConfig();
#endif
DOMElement* child;
#ifndef SHIBSP_LITE
- if (conf.isEnabled(SPConfig::OutOfProcess)) {
+ if (spConf.isEnabled(SPConfig::OutOfProcess)) {
XMLToolingConfig& xmlConf = XMLToolingConfig::getConfig();
// First build any StorageServices.
child = XMLHelper::getFirstChildElement(e, _StorageService);
if (!t.empty()) {
try {
log.info("building StorageService (%s) of type %s...", id.c_str(), t.c_str());
- m_outer->m_storage[id] = xmlConf.StorageServiceManager.newPlugin(t.c_str(), child);
+ conf->m_storage[id] = xmlConf.StorageServiceManager.newPlugin(t.c_str(), child);
}
catch (exception& ex) {
log.crit("failed to instantiate StorageService (%s): %s", id.c_str(), ex.what());
child = XMLHelper::getNextSiblingElement(child, _StorageService);
}
- if (m_outer->m_storage.empty()) {
+ if (conf->m_storage.empty()) {
log.info("no StorageService plugin(s) installed, using (mem) in-memory instance");
- m_outer->m_storage["mem"] = xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE, nullptr);
+ conf->m_storage["mem"] = xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE, nullptr);
}
// Replay cache.
if (child) {
string ssid(XMLHelper::getAttrString(child, nullptr, _StorageService));
if (!ssid.empty()) {
- if (m_outer->m_storage.count(ssid)) {
+ if (conf->m_storage.count(ssid)) {
log.info("building ReplayCache on top of StorageService (%s)...", ssid.c_str());
- replaySS = m_outer->m_storage[ssid];
+ replaySS = conf->m_storage[ssid];
}
else {
log.error("unable to locate StorageService (%s), using arbitrary instance for ReplayCache", ssid.c_str());
- replaySS = m_outer->m_storage.begin()->second;
+ replaySS = conf->m_storage.begin()->second;
}
}
else {
log.info("no StorageService specified for ReplayCache, using arbitrary instance");
- replaySS = m_outer->m_storage.begin()->second;
+ replaySS = conf->m_storage.begin()->second;
}
}
else {
log.info("no ReplayCache specified, using arbitrary StorageService instance");
- replaySS = m_outer->m_storage.begin()->second;
+ replaySS = conf->m_storage.begin()->second;
}
xmlConf.setReplayCache(new ReplayCache(replaySS));
if (child) {
string ssid(XMLHelper::getAttrString(child, nullptr, _StorageService));
if (!ssid.empty()) {
- if (m_outer->m_storage.count(ssid)) {
+ if (conf->m_storage.count(ssid)) {
log.info("building ArtifactMap on top of StorageService (%s)...", ssid.c_str());
- samlConf.setArtifactMap(new ArtifactMap(child, m_outer->m_storage[ssid]));
+ samlConf.setArtifactMap(new ArtifactMap(child, conf->m_storage[ssid]));
}
else {
log.error("unable to locate StorageService (%s), using in-memory ArtifactMap", ssid.c_str());
string t(XMLHelper::getAttrString(child, nullptr, _type));
if (!t.empty()) {
log.info("building SessionCache of type %s...", t.c_str());
- m_outer->m_sessionCache = conf.SessionCacheManager.newPlugin(t.c_str(), child);
+ conf->m_sessionCache = spConf.SessionCacheManager.newPlugin(t.c_str(), child);
}
}
- if (!m_outer->m_sessionCache) {
+ if (!conf->m_sessionCache) {
log.info("no SessionCache specified, using StorageService-backed instance");
- m_outer->m_sessionCache = conf.SessionCacheManager.newPlugin(STORAGESERVICE_SESSION_CACHE, nullptr);
+ conf->m_sessionCache = spConf.SessionCacheManager.newPlugin(STORAGESERVICE_SESSION_CACHE, nullptr);
}
}
-XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log)
+XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, Category& log)
: m_requestMapper(nullptr),
#ifndef SHIBSP_LITE
m_policy(nullptr),
#endif
- m_outer(outer), m_document(nullptr)
+ m_document(nullptr)
{
#ifdef _DEBUG
xmltooling::NDC ndc("XMLConfigImpl");
#ifndef SHIBSP_LITE
if (first)
- m_outer->m_tranLog = new TransactionLog();
+ outer->m_tranLog = new TransactionLog();
#endif
}
// Instantiate the ListenerService and SessionCache objects.
if (conf.isEnabled(SPConfig::Listener))
- doListener(e, log);
+ doListener(e, outer, log);
#ifndef SHIBSP_LITE
- if (m_outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {
- m_outer->m_listener->regListener("set::RelayState", const_cast<XMLConfig*>(m_outer));
- m_outer->m_listener->regListener("get::RelayState", const_cast<XMLConfig*>(m_outer));
- m_outer->m_listener->regListener("set::PostData", const_cast<XMLConfig*>(m_outer));
- m_outer->m_listener->regListener("get::PostData", const_cast<XMLConfig*>(m_outer));
+ if (outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {
+ outer->m_listener->regListener("set::RelayState", outer);
+ outer->m_listener->regListener("get::RelayState", outer);
+ outer->m_listener->regListener("set::PostData", outer);
+ outer->m_listener->regListener("get::PostData", outer);
}
#endif
if (conf.isEnabled(SPConfig::Caching))
- doCaching(e, log);
+ doCaching(e, outer, log);
} // end of first-time-only stuff
// Back to the fully dynamic stuff...next up is the RequestMapper.
log.fatal("can't build default Application object, missing conf:ApplicationDefaults element?");
throw ConfigurationException("can't build default Application object, missing conf:ApplicationDefaults element?");
}
- XMLApplication* defapp = new XMLApplication(m_outer, pp, child);
+ XMLApplication* defapp = new XMLApplication(outer, pp, child);
m_appmap[defapp->getId()] = defapp;
// Load any overrides.
child = XMLHelper::getFirstChildElement(child, ApplicationOverride);
while (child) {
- auto_ptr<XMLApplication> iapp(new XMLApplication(m_outer, pp, child, defapp));
+ auto_ptr<XMLApplication> iapp(new XMLApplication(outer, pp, child, defapp));
if (m_appmap.count(iapp->getId()))
log.crit("found conf:ApplicationOverride element with duplicate id attribute (%s), skipping it", iapp->getId());
else {
child = XMLHelper::getNextSiblingElement(child, ApplicationOverride);
}
+
+ // Check for extra AuthTypes to recognize.
+ if (conf.isEnabled(SPConfig::InProcess)) {
+ const PropertySet* inprocs = getPropertySet("InProcess");
+ if (inprocs) {
+ pair<bool,const char*> extraAuthTypes = inprocs->getString("extraAuthTypes");
+ if (extraAuthTypes.first) {
+ string types=extraAuthTypes.second;
+ unsigned int j_types=0;
+ for (unsigned int i_types=0; i_types < types.length(); i_types++) {
+ if (types.at(i_types) == ' ') {
+ outer->m_authTypes.insert(types.substr(j_types, i_types - j_types));
+ j_types = i_types + 1;
+ }
+ }
+ outer->m_authTypes.insert(types.substr(j_types, types.length() - j_types));
+ }
+ }
+ }
}
catch (exception&) {
cleanup();
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="binding\ProtocolProvider.h" />\r
+ <ClInclude Include="GSSRequest.h" />\r
<ClInclude Include="handler\LogoutInitiator.h" />\r
<ClInclude Include="remoting\impl\SocketListener.h" />\r
<ClInclude Include="AbstractSPRequest.h" />\r
<ClInclude Include="binding\ProtocolProvider.h">\r
<Filter>Header Files\binding</Filter>\r
</ClInclude>\r
+ <ClInclude Include="GSSRequest.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<ResourceCompile Include="shibsp.rc">\r
<ItemGroup>\r
<ClCompile Include="AbstractSPRequest.cpp" />\r
<ClCompile Include="Application.cpp" />\r
+ <ClCompile Include="attribute\Base64AttributeDecoder.cpp" />\r
<ClCompile Include="binding\impl\XMLProtocolProvider.cpp" />\r
<ClCompile Include="handler\impl\DiscoveryFeed.cpp" />\r
<ClCompile Include="handler\impl\LogoutInitiator.cpp" />\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="binding\ProtocolProvider.h" />\r
+ <ClInclude Include="GSSRequest.h" />\r
<ClInclude Include="handler\LogoutInitiator.h" />\r
<ClInclude Include="remoting\impl\SocketListener.h" />\r
<ClInclude Include="AbstractSPRequest.h" />\r
<ClCompile Include="handler\impl\DiscoveryFeed.cpp">\r
<Filter>Source Files\handler\impl</Filter>\r
</ClCompile>\r
+ <ClCompile Include="attribute\Base64AttributeDecoder.cpp">\r
+ <Filter>Source Files\attribute</Filter>\r
+ </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="remoting\impl\SocketListener.h">\r
<ClInclude Include="binding\ProtocolProvider.h">\r
<Filter>Header Files\binding</Filter>\r
</ClInclude>\r
+ <ClInclude Include="GSSRequest.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<ResourceCompile Include="shibsp.rc">\r