From: Katy Feng Date: Thu, 5 Oct 2023 17:35:27 +0000 (-0700) Subject: Remove support for building with xml-security-c and xerces-c. X-Git-Tag: stable-12.4.0~83 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aeb469eda96b721bb382e294f63342139c7ae694;p=thirdparty%2Fopen-vm-tools.git Remove support for building with xml-security-c and xerces-c. --- diff --git a/open-vm-tools/configure.ac b/open-vm-tools/configure.ac index b39422b4b..49293f6e5 100644 --- a/open-vm-tools/configure.ac +++ b/open-vm-tools/configure.ac @@ -793,86 +793,50 @@ fi AC_ARG_ENABLE([vgauth], [AS_HELP_STRING([--disable-vgauth], - [do not build vgauth.])], + [do not build vgauth])], [ if test "$with_pam" = "no" -a "$enableval" = "yes"; then AC_MSG_ERROR([Cannot enable vgauth without PAM. Please configure without --without-pam or without --enable-vgauth.]) fi enable_vgauth="$enableval" - use_xmlsec1=yes ], [ if test "$with_pam" = "no"; then enable_vgauth="no" - use_xmlsec1="no" AC_MSG_WARN("Building without PAM; vgauth will be disabled.") elif test "$os" = "linux"; then enable_vgauth=yes - use_xmlsec1=yes else enable_vgauth=no - use_xmlsec1=yes fi ]) -AC_ARG_ENABLE([xmlsec1], - [AS_HELP_STRING([--enable-xmlsec1], - [build vgauth with xmlsec1 instead of xml-security-c (on by default).])], - [use_xmlsec1="$enableval"], - [use_xmlsec1=yes]) - -AC_ARG_ENABLE([xmlsecurity], - [AS_HELP_STRING([--enable-xmlsecurity], - [build vgauth with xml-security-c instead of xmlsec1 (off by default).])], - [ - if test "$enableval" = "yes"; then - use_xmlsec1="no" - else - use_xmlsec1="yes" - fi - ], - []) - # -# Check for openssl, xerces-c and xml-security-c +# Check for openssl, xmlsec1, xml2 # AC_ARG_WITH([ssl], [AS_HELP_STRING([--without-ssl], - [compiles without openssl support (disables vgauth).])], - [ - enable_vgauth=no - ], - [with_ssl=yes]) - -AC_ARG_WITH([xmlsecurity], - [AS_HELP_STRING([--without-xmlsecurity], - [compiles without xml-security-c support (disables vgauth).])], - [enable_vgauth=no], - [with_xmlsecurity=yes]) - -AC_ARG_WITH([xerces], - [AS_HELP_STRING([--without-xerces], - [compiles without xerces support (disables vgauth).])], - [enable_vgauth=no], - [with_xerces=yes]) + [compiles without openssl support (disables vgauth)])], + [if test "$withval" = "no"; then enable_vgauth = "no"; fi], + [with_ssl="yes"]) AC_ARG_WITH([xmlsec1], [AS_HELP_STRING([--without-xmlsec1], - [compiles without xmlsec1 support (disables vgauth).])], - [enable_vgauth=no], - [with_xmlsec1=yes]) + [compiles without xmlsec1 support (disables vgauth)])], + [if test "$withval" = "no"; then enable_vgauth = "no"; fi], + [with_xmlsec1="yes"]) AC_ARG_WITH([xml2], [AS_HELP_STRING([--without-xml2], - [compiles without xml2 support (disables vgauth).])], - [enable_vgauth=no], - [with_xml2=yes]) + [compiles without xml2 support (disables vgauth)])], + [if test "$withval" = "no"; then enable_vgauth = "no"; fi], + [with_xml2="yes"]) AC_ARG_WITH([tirpc], [AS_HELP_STRING([--without-tirpc], - [compiles with/without libtirpc.])], + [compiles with/without libtirpc])], [], [with_tirpc=auto]) @@ -890,59 +854,32 @@ if test "$enable_vgauth" = "yes" ; then [BIO_new_file], [], [AC_VMW_LIB_ERROR([SSL], [ssl])]) -fi -if test "$enable_vgauth" = "yes"; then CPPFLAGS="$CPPFLAGS -DUSE_VGAUTH" - if test "$use_xmlsec1" = "yes"; then - AC_VMW_DEFAULT_FLAGS([XML2]) - AC_VMW_CHECK_LIB([xml2], - [XML2], - [], - [], - [], - [], - [], - [], - [AC_VMW_LIB_ERROR([XML2], [xml2])]) - - # Multiple distros built xmlsec1 with -DXMLSEC_NO_SIZE_T but - # their xmlssec1-config --cflags doesn't properly report it, - # so force it on. - AC_VMW_DEFAULT_FLAGS([XMLSEC1]) - AC_VMW_CHECK_LIB([xmlsec1], - [XMLSEC1], - [], - [xmlsec1-config], - [], - [xmlsec/xmlsec.h], - [xmlSecCheckVersionExt], - [XMLSEC1_CPPFLAGS="$XMLSEC1_CPPFLAGS -DXMLSEC_NO_SIZE_T"], - [AC_VMW_LIB_ERROR([XMLSEC1], [xmlsec1])]) - - else - AC_VMW_DEFAULT_FLAGS([XERCES]) - AC_VMW_CHECK_LIB([xerces-c], - [XERCES], - [], - [], - [], - [], - [], - [], - [AC_VMW_LIB_ERROR([XERCES], [xerces])]) - - AC_VMW_DEFAULT_FLAGS([XMLSECURITY]) - AC_VMW_CHECK_LIB([xml-security-c], - [XMLSECURITY], - [], - [], - [], - [], - [], - [], - [AC_VMW_LIB_ERROR([XMLSECURITY], [xmlsecurity])]) - fi + AC_VMW_DEFAULT_FLAGS([XML2]) + AC_VMW_CHECK_LIB([xml2], + [XML2], + [], + [], + [], + [], + [], + [], + [AC_VMW_LIB_ERROR([XML2], [xml2])]) + +# Multiple distros built xmlsec1 with -DXMLSEC_NO_SIZE_T but +# their xmlssec1-config --cflags doesn't properly report it, +# so force it on. + AC_VMW_DEFAULT_FLAGS([XMLSEC1]) + AC_VMW_CHECK_LIB([xmlsec1], + [XMLSEC1], + [], + [xmlsec1-config], + [], + [xmlsec/xmlsec.h], + [xmlSecCheckVersionExt], + [XMLSEC1_CPPFLAGS="$XMLSEC1_CPPFLAGS -DXMLSEC_NO_SIZE_T"], + [AC_VMW_LIB_ERROR([XMLSEC1], [xmlsec1])]) fi # @@ -1711,13 +1648,12 @@ AM_CONDITIONAL(USE_SLASH_PROC, test "$os" = "linux") AM_CONDITIONAL(ENABLE_CONTAINERINFO, test "$enable_containerinfo" = "yes") AM_CONDITIONAL(ENABLE_DEPLOYPKG, test "$enable_deploypkg" = "yes") AM_CONDITIONAL(ENABLE_VGAUTH, test "$enable_vgauth" = "yes") -AM_CONDITIONAL(USE_XMLSEC1, test "$use_xmlsec1" = "yes") AM_CONDITIONAL(HAVE_VSOCK, test "$os" = "linux") AM_CONDITIONAL(HAVE_MKDTEMP, test "$have_mkdtemp" = "yes") AM_CONDITIONAL(HAVE_UDEV, test "$have_udev" = "yes") AM_CONDITIONAL(ENABLE_RESOLUTIONKMS, test "x$enable_resolutionkms" = "xyes") AM_CONDITIONAL(ENABLE_VMWGFXCTRL, test "x$enable_vmwgfxctrl" = "xyes") -AM_CONDITIONAL(VGAUTH_USE_CXX, test "$with_icu" = "yes" -o "$use_xmlsec1" != "yes") +AM_CONDITIONAL(VGAUTH_USE_CXX, test "$with_icu" = "yes") AM_CONDITIONAL(ENABLE_LIBAPPMONITOR, test "$enable_libappmonitor" = "yes") AM_CONDITIONAL(ENABLE_SDMP, test "$enable_servicediscovery" = "yes") AM_CONDITIONAL(ENABLE_SALTMINION, test "$enable_saltminion" = "yes" -a \( "$arch" = "x64" \) ) diff --git a/open-vm-tools/vgauth/service/Makefile.am b/open-vm-tools/vgauth/service/Makefile.am index 54df26c18..9f46a9a93 100644 --- a/open-vm-tools/vgauth/service/Makefile.am +++ b/open-vm-tools/vgauth/service/Makefile.am @@ -1,5 +1,5 @@ ################################################################################ -### Copyright (C) 2014-2020, 2022 VMware, Inc. All rights reserved. +### Copyright (C) 2014-2020, 2022, 2023 VMware, Inc. All rights reserved. ### ### This program is free software; you can redistribute it and/or modify ### it under the terms of version 2 of the GNU General Public License as @@ -30,11 +30,7 @@ VGAuthService_SOURCES += ../serviceImpl/filePosix.c VGAuthService_SOURCES += ../serviceImpl/netPosix.c VGAuthService_SOURCES += ../serviceImpl/proto.c VGAuthService_SOURCES += ../serviceImpl/random.c -if USE_XMLSEC1 VGAuthService_SOURCES += ../serviceImpl/saml-xmlsec1.c -else -VGAuthService_SOURCES += ../serviceImpl/saml-xml-security-c.cpp -endif VGAuthService_SOURCES += ../serviceImpl/service.c VGAuthService_SOURCES += ../serviceImpl/ticket.c VGAuthService_SOURCES += ../serviceImpl/verify.c @@ -64,12 +60,7 @@ VGAuthService_SCRIPTS += ../serviceImpl/schemas/catalog.xml VGAuthService_CPPFLAGS = VGAuthService_CPPFLAGS += @GLIB2_CPPFLAGS@ -if USE_XMLSEC1 VGAuthService_CPPFLAGS += @XMLSEC1_CPPFLAGS@ -else -VGAuthService_CPPFLAGS += @XERCES_CPPFLAGS@ -VGAuthService_CPPFLAGS += @XMLSECURITY_CPPFLAGS@ -endif VGAuthService_CPPFLAGS += @SSL_CPPFLAGS@ VGAuthService_CPPFLAGS += -I$(top_srcdir)/vgauth/public VGAuthService_CPPFLAGS += -I$(top_srcdir)/vgauth/common @@ -78,14 +69,7 @@ VGAuthService_CPPFLAGS += -I$(top_srcdir)/vgauth/serviceImpl VGAuthService_LDADD = VGAuthService_LDADD += @GLIB2_LIBS@ VGAuthService_LDADD += @GTHREAD_LIBS@ -if USE_XMLSEC1 VGAuthService_LDADD += @XMLSEC1_LIBS@ -else -VGAuthService_LDADD += @XERCES_LIBS@ -VGAuthService_LDADD += @XMLSECURITY_LIBS@ -VGAuthService_LDADD += -lxerces-c -VGAuthService_LDADD += -lxml-security-c -endif VGAuthService_LDADD += @SSL_LIBS@ VGAuthService_LDADD += -lssl VGAuthService_LDADD += -lcrypto diff --git a/open-vm-tools/vgauth/serviceImpl/saml-xml-security-c.cpp b/open-vm-tools/vgauth/serviceImpl/saml-xml-security-c.cpp deleted file mode 100644 index 7fca8ba63..000000000 --- a/open-vm-tools/vgauth/serviceImpl/saml-xml-security-c.cpp +++ /dev/null @@ -1,1280 +0,0 @@ -/********************************************************* - * Copyright (c) 2011-2017,2023 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation version 2.1 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - *********************************************************/ - -/** - * @file saml-xml-security-c.cpp - * - * Code for authenticating users based on SAML tokens. - */ - -#include -#include -#include -#include - -#undef WIN32_LEAN_AND_MEAN // XSEC unconditionally redefines this -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * XXX - * - * Optimization idea: stash a hash (SHA512) of a valid token, and bypass - * the full assertion process when we see that token again. The expiration - * date of the token must also be saved off (and beware the time skew issue). - * - * Note that there's some extra complexity here: - * - * 1 - AddAlias sets up a cert/user mapping - * 2 - a SAML token is used (and cached) using this cert/user combo - * 3 - RemoveAlias removes the combo - * 4 - the cached token still works - * - * So the cache should only bypass the token validation, not the certificate - * check in ServiceVerifyAndCheckTrustCertChainForSubject() - * - * Also TBD is how much this buys us in the real world. With short - * token lifetimes, its less interesting. Its also possible that - * it will have no measureable affect because the token verification - * will be lost in the noise of the API plumbing from VC->hostd->VMX->tools. - * - * The security folks have signed off on this, so long as we store only - * in memory. - * - */ - -/* - * XXX - * - * We should be a lot smarter about this, but this gets QE - * moving. - */ -#define SAML_TOKEN_PREFIX "saml:" -#define SAML_TOKEN_SSO_PREFIX "saml2:" - -extern "C" { -#include "prefs.h" -#include "serviceInt.h" -} -#include "samlInt.hpp" - - -/** - * Error handler used to log warnings from the XML parser. - */ - -class SAMLErrorHandler : public ErrorHandler { -public: - static void - printWarning(const SAXParseException &e, - const char *msg) - { - SAMLStringWrapper nativeMsg(e.getMessage()); - - /* - * XXX - * - * These functions were inlined on older compilers but are exported - * from libstdc++.so on newer compilers (4.4.3). Avoid using them to - * avoid the newer dependency. - * - * _ZNSo9_M_insertIyEERSoT_@@GLIBCXX_3.4.9 - * std::basic_ostream >& - * std::basic_ostream >:: - * _M_insert(unsigned long long) - * aka: operator<<(uint64_t) - * - * _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_i@@GLIBCXX_3.4.9 - * std::basic_ostream >& - * std::__ostream_insert > - * (std::basic_ostream >&, - * char const*, int) - * aka: operator<<(std::string) - * - */ - Debug("SAML: %s: %s (line=%d, col=%d)\n", - msg, nativeMsg.c_str(), - (int) e.getLineNumber(), (int) e.getColumnNumber()); - -#ifdef avoid_this_usage - /* - * I'm tired of defining format modifier macros, so let's use - * stringstream to handle e.getLineNumber()'s return type. - */ - - std::stringstream ss; - - ss << msg << ": " << nativeMsg.c_str() << "" << " (line=" << - e.getLineNumber() << ", col=" << e.getColumnNumber() << ")"; - - Debug("SAML: %s.\n", ss.str().c_str()); -#endif - } - - void - warning(const SAXParseException &e) - { - printWarning(e, "warning"); - } - - void - error(const SAXParseException &e) - { - printWarning(e, "error"); - } - - void - fatalError (const SAXParseException &e) - { - printWarning(e, "fatal error"); - } - - void - resetErrors() - { - } -}; - - - -/** - * The XML schema files needed to perform validating parsing of the - * SAML assertions. Note: the order is important, since schemas need - * to be loaded before any schema that depends on them, so don't change - * the order. - */ -static const char *schemas[] = { - "xml.xsd", - "XMLSchema.xsd", - "xmldsig-core-schema.xsd", - "xenc-schema.xsd", - "saml-schema-assertion-2.0.xsd", -}; - - -/** - * An in-memory cache for XML schemas. - */ -static XMLGrammarPool *pool = NULL; - -static int clockSkewAdjustment = VGAUTH_PREF_DEFAULT_CLOCK_SKEW_SECS; - -static bool SAMLLoadSchema(XercesDOMParser &parser, - const SAMLGlibString &schemaDir, - const char *filename); -static DOMDocument *SAMLValidateSchemaAndParse(XercesDOMParser &parser, - const char *xmlText); - -static bool SAMLCheckSubject(const DOMDocument *doc, - SAMLTokenData &token); - -static bool SAMLCheckConditions(const DOMDocument *doc, - SAMLTokenData &token); - -static bool SAMLCheckTimeAttr(const DOMElement *elem, const char *attrName, - bool beforeNow); - -static bool SAMLCheckAudience(const XMLCh *audience); - -static bool SAMLCheckSignature(DOMDocument *doc, - gboolean hostVerified, - vector &certs); - -static bool SAMLCheckReference(const DOMDocument *doc, DSIGSignature *sig); - -static DOMElement *SAMLFindChildByName(const DOMElement *elem, - const char *name); - -static auto_ptr SAMLFindKey(const XSECEnv &secEnv, - const DOMElement *sigElem); - - -/* - ****************************************************************************** - * SAML_Init -- */ /** - * - * Performs any initialization needed for SAML processing. - * - * @return VGAUTH_E_OK on success, VGAuthError on failure - * - ****************************************************************************** - */ - -VGAuthError -SAML_Init() -{ - try { - XMLPlatformUtils::Initialize(); - XSECPlatformUtils::Initialise(); - - auto_ptr myPool = SAMLCreateAndPopulateGrammarPool(); - if (NULL == myPool.get()) { - return VGAUTH_E_FAIL; - } - - pool = myPool.release(); - - clockSkewAdjustment = Pref_GetInt(gPrefs, VGAUTH_PREF_CLOCK_SKEW_SECS, - VGAUTH_PREF_GROUP_NAME_SERVICE, - VGAUTH_PREF_DEFAULT_CLOCK_SKEW_SECS); - Log("%s: Allowing %d of clock skew for SAML date validation\n", - __FUNCTION__, clockSkewAdjustment); - - return VGAUTH_E_OK; - } catch (const XMLException& e) { - SAMLStringWrapper msg(e.getMessage()); - - Warning("Failed to initialize Xerces: %s.\n", msg.c_str()); - return VGAUTH_E_FAIL; - } catch (...) { - // We're called from C code, so don't let any exceptions out. - Warning("%s: Unexpected exception.\n", __FUNCTION__); - return VGAUTH_E_FAIL; - } -} - - -/* - ****************************************************************************** - * SAMLCreateAndPopulateGrammarPool -- */ /** - * - * Creates a grammar pool that is populates with cached grammars representing - * the XML schemas needed for SAML validation. - * - * @return A heap allocated grammar pool (must be freed with operator - * delete) or NULL on failure. - * - ****************************************************************************** - */ - -auto_ptr -SAMLCreateAndPopulateGrammarPool() -{ - auto_ptr newPool(new XMLGrammarPoolImpl(XMLPlatformUtils::fgMemoryManager)); - - /* - * Create a parser instance to load all the schemas, so they can - * be cached for later. In addition to making parsing faster, we - * need to cache them so that Xerces does not try to download - * schemas from the web when one is referenced or imported by another - * schema. - */ - XercesDOMParser parser(NULL, XMLPlatformUtils::fgMemoryManager, - newPool.get()); - - gchar *dir = Pref_GetString(gPrefs, VGAUTH_PREF_SAML_SCHEMA_DIR, - VGAUTH_PREF_GROUP_NAME_SERVICE, NULL); - if (NULL == dir) { -#ifdef _WIN32 - /* - * To make life easier for the Windows installer, assume - * the schema directory is next to the executable. Also - * check in ../ in case we're in a dev environment. - */ - dir = g_build_filename(gInstallDir, "schemas", NULL); - if (!(g_file_test(dir, G_FILE_TEST_EXISTS) && - g_file_test(dir, G_FILE_TEST_IS_DIR))) { - - gchar *newDir = g_build_filename(gInstallDir, "..", "schemas", NULL); - - Debug("%s: schemas not found in Windows install loc '%s'," - " trying dev location of '%s'\n", __FUNCTION__, dir, newDir); - - g_free(dir); - dir = newDir; - } -#else - /* - * XXX -- clean this up to make a better default for Linux. - */ - dir = g_build_filename(gInstallDir, "..", "schemas", NULL); -#endif - } - Log("%s: Using '%s' for SAML schemas\n", __FUNCTION__, dir); - SAMLGlibString schemaDir(dir); - - for (unsigned int i = 0; i < G_N_ELEMENTS(schemas); i++) { - if (!SAMLLoadSchema(parser, schemaDir, schemas[i])) { - return auto_ptr(NULL); - } - } - - return newPool; -} - - -/* - ****************************************************************************** - * SAML_Shutdown -- */ /** - * - * Performs any clean-up of resources needed for SAML processing. - * - ****************************************************************************** - */ - -void -SAML_Shutdown() -{ - try { - delete pool; - pool = NULL; - XSECPlatformUtils::Terminate(); - XMLPlatformUtils::Terminate(); - } catch (...) { - // We're called from C code, so don't let any exceptions out. - Warning("%s: Unexpected exception.\n", __FUNCTION__); - } -} - - -/* - ****************************************************************************** - * SAML_Reload -- */ /** - * - * Reload any in-memory state used by the SAML module. - * - ****************************************************************************** - */ - -void -SAML_Reload() -{ - ASSERT(pool != NULL); - - auto_ptr myPool = SAMLCreateAndPopulateGrammarPool(); - if (NULL == myPool.get()) { - Warning("%s: Failed to reload SAML state. Using old settings.\n", - __FUNCTION__); - return; - } - - delete pool; - pool = myPool.release(); -} - - -/* - ****************************************************************************** - * SAMLLoadSchema -- */ /** - * - * Loads a schema into the grammar pool used by the given parser. - * - * @param[in] parser The parser to load the schema with. - * @param[in] schemaDir The full path to the directory containing the schema. - * @param[in] filename The name of the XML schema file. - * - * @return true if the schema file was successfully loaded, false otherwise. - * - ****************************************************************************** - */ - -static bool -SAMLLoadSchema(XercesDOMParser &parser, - const SAMLGlibString &schemaDir, - const char *filename) -{ - SAMLGlibString schemaPath(g_build_filename(schemaDir.c_str(), filename, - NULL)); - Grammar *g = parser.loadGrammar(schemaPath.c_str(), - Grammar::SchemaGrammarType, true); - if (g == NULL) { - /* - * The parser complains even with official schemas, so we don't - * normally set an error handler. However, this should not fail since - * we control these files, so try again with logging, so we can see - * what went wrong. - */ - SAMLErrorHandler errorHandler; - parser.setErrorHandler(&errorHandler); - - g = parser.loadGrammar(schemaPath.c_str(), Grammar::SchemaGrammarType, - true); - - Warning("Failed to load XML Schema from %s.\n", schemaPath.c_str()); - return false; - } - - return true; -} - - -/* - ****************************************************************************** - * SAML_VerifyBearerToken -- */ /** - * - * Determines whether the SAML bearer token can be used to authenticate. - * A token consists of a single SAML assertion. - * - * This is currently only used from the test code. - * - * @param[in] xmlText The text of the SAML assertion. - * @param[in] userName Optional username to authenticate as. - * @param[out] userNameOut The user that the token has authenticated as. - * @param[out] subjNameOut The subject in the token. - * @param[out] verifySi The subjectInfo associated with the entry - * in the ID provider store used to verify the - * SAML cert. - * - * @return VGAUTH_E_OK on success, VGAuthError on failure - * - ****************************************************************************** - */ - -VGAuthError -SAML_VerifyBearerToken(const char *xmlText, - const char *userName, - char **userNameOut, - char **subjNameOut, - ServiceAliasInfo **verifyAi) -{ - try { - vector certs; - VGAuthError err; - SAMLTokenData token; - - err = SAMLVerifyAssertion(xmlText, - FALSE, // use original mode - token, certs); - if (VGAUTH_E_OK != err) { - return err; - } - - return err; - } catch (XSECException &e) { - SAMLStringWrapper msg(e.getMsg()); - - Warning("XSec exception while verifying assertion: %s.\n", msg.c_str()); - return VGAUTH_E_FAIL; - } catch (const XMLException& e) { - SAMLStringWrapper msg(e.getMessage()); - - Warning("Xerces exception while verifying assertion: %s.\n", - msg.c_str()); - return VGAUTH_E_FAIL; - } catch (...) { - // We're called from C code, so don't let any exceptions out. - Warning("Unexpected exception.\n"); - return VGAUTH_E_FAIL; - } -} - - -/* - ****************************************************************************** - * SAML_VerifyBearerTokenAndChain -- */ /** - * - * Determines whether the SAML bearer token can be used to authenticate. - * A token consists of a single SAML assertion. - * The token must first be verified, then the certificate chain used - * verify it must be checked against the appropriate certificate store. - * - * @param[in] xmlText The text of the SAML assertion. - * @param[in] userName Optional username to authenticate as. - * @param[in] hostVerified If true, skip signature verification. - * @param[out] userNameOut The user that the token has authenticated as. - * @param[out] subjNameOut The subject in the token. - * @param[out] verifySi The subjectInfo associated with the entry - * in the ID provider store used to verify the - * SAML cert. - * - * @return VGAUTH_E_OK on success, VGAuthError on failure - * - ****************************************************************************** - */ - -VGAuthError -SAML_VerifyBearerTokenAndChain(const char *xmlText, - const char *userName, - gboolean hostVerified, - char **userNameOut, - char **subjNameOut, - ServiceAliasInfo **verifyAi) -{ - *userNameOut = NULL; - *subjNameOut = NULL; - *verifyAi = NULL; - - try { - vector certs; - VGAuthError err; - SAMLTokenData token; - char **pemCerts; - ServiceSubject subj; - int i; - - err = SAMLVerifyAssertion(xmlText, - hostVerified, - token, certs); - if (VGAUTH_E_OK != err) { - return err; - } - - pemCerts = (char **) g_malloc0(sizeof(char *) * certs.size()); - for (i = 0; i < (int) certs.size(); i++) { - pemCerts[i] = g_strdup(certs[i].c_str()); - } - subj.type = SUBJECT_TYPE_NAMED; - if (subjNameOut) { - *subjNameOut = g_strdup(token.subjectName.c_str()); - } - subj.name = g_strdup(token.subjectName.c_str()); - err = ServiceVerifyAndCheckTrustCertChainForSubject((int) certs.size(), - (const char **) pemCerts, - userName, - &subj, - userNameOut, - verifyAi); - Debug("%s: ServiceVerifyAndCheckTrustCertChainForSubject() returned " VGAUTHERR_FMT64 "\n", __FUNCTION__, err); - - for (i = 0; i < (int) certs.size(); i++) { - g_free(pemCerts[i]); - } - g_free(pemCerts); - g_free(subj.name); - return err; - } catch (XSECException &e) { - SAMLStringWrapper msg(e.getMsg()); - - Warning("XSec exception while verifying assertion: %s.\n", msg.c_str()); - return VGAUTH_E_FAIL; - } catch (const XMLException& e) { - SAMLStringWrapper msg(e.getMessage()); - - Warning("Xerces exception while verifying assertion: %s.\n", - msg.c_str()); - return VGAUTH_E_FAIL; - } catch (...) { - // We're called from C code, so don't let any exceptions out. - Warning("Unexpected exception.\n"); - return VGAUTH_E_FAIL; - } -} - - -/* - ****************************************************************************** - * SAMLVerifyAssertion -- */ /** - * - * Performs the following checks to validate a SAML assertion. - * 1) Checks that the XML document is well formed according to the SAML 2.0 - * Assertion XML schema. - * 2) Check that the assertion is signed by a certificate contained within - * the assertion. - * 3) TODO: Check that the assertion contains a Subject element, and that - * Subject element should contain a SubjectConfirmation element. The - * SubjectConfirmation method must be "bearer" - * ("urn:oasis:names:tc:SAML:2.0:cm:bearer"). - * 4) The Conditions element for the assertion must be met in terms of - * any "NotBefore" or "NotOnOrAfter" information. - * The chain of certs used to verify the signature will be returned via @a - * certs. - * - * @param[in] xmlText - * @param[in] hostVerified If true, skip signature verification. - * @param[out] token The interesting bits extracted from the xmlText. - * @param[out] certs If the SAML assertion is verified, then this will - * contain the certificate chain for the issuer. - * Each certificate will be base64 encoded (but without - * the PEM-style bookends), with the issuer's cert - * at element 0. - * - * @return VGAUTH_E_OK on success, VGAuthError on failure - * - ****************************************************************************** - */ - -VGAuthError -SAMLVerifyAssertion(const char *xmlText, - gboolean hostVerified, - SAMLTokenData &token, - vector &certs) -{ - XercesDOMParser parser(NULL, XMLPlatformUtils::fgMemoryManager, pool); - SAMLErrorHandler errorHandler; - SecurityManager sm; - - parser.setErrorHandler(&errorHandler); - - // prevent the billion laughs attack -- put a limit on entity expansions - sm.setEntityExpansionLimit(100); - parser.setSecurityManager(&sm); - - DOMDocument *doc = SAMLValidateSchemaAndParse(parser, xmlText); - if (NULL == doc) { - return VGAUTH_E_AUTHENTICATION_DENIED; - } - - const DOMElement *s = SAMLFindChildByName(doc->getDocumentElement(), - SAML_TOKEN_PREFIX"Subject"); - if (NULL == s) { - Debug("Couldn't find " SAML_TOKEN_PREFIX " in token\n"); - s = SAMLFindChildByName(doc->getDocumentElement(), - SAML_TOKEN_SSO_PREFIX"Subject"); - if (NULL == s) { - Debug("Couldn't find " SAML_TOKEN_SSO_PREFIX " in token\n"); - Warning("No recognized tags in token; punting\n"); - return VGAUTH_E_AUTHENTICATION_DENIED; - } else { - Debug("Found " SAML_TOKEN_SSO_PREFIX " in token\n"); - token.isSSOToken = true; - token.ns = SAML_TOKEN_SSO_PREFIX; - } - } else { - Debug("Found " SAML_TOKEN_PREFIX " in token\n"); - token.isSSOToken = false; - token.ns = SAML_TOKEN_PREFIX; - } - - if (!SAMLCheckSubject(doc, token)) { - return VGAUTH_E_AUTHENTICATION_DENIED; - } - - if (!SAMLCheckConditions(doc, token)) { - return VGAUTH_E_AUTHENTICATION_DENIED; - } - - if (!SAMLCheckSignature(doc, - hostVerified, - certs)) { - return VGAUTH_E_AUTHENTICATION_DENIED; - } - - return VGAUTH_E_OK; -} - - -/* - ****************************************************************************** - * SAMLValidateSchemaAndParse -- */ /** - * - * Checks that the XML document is well formed according to the SAML 2.0 - * Assertion XML schema. - * - * @param[in] parser The parser to use with the XML document. - * @param[in] xmlText The text of the SAML assertion. - * - * @return A pointer to a DOMDocument instance that represents the parsed - * SAML assertion or NULL if the document was not valid. The memory - * used by the DOMDocument is owned by the parser. - * - ****************************************************************************** - */ - -static DOMDocument * -SAMLValidateSchemaAndParse(XercesDOMParser &parser, - const char *xmlText) -{ - parser.setDoNamespaces(true); - parser.setDoSchema(true); - parser.setValidationScheme(AbstractDOMParser::Val_Always); - parser.useCachedGrammarInParse(true); - - MemBufInputSource in(reinterpret_cast(xmlText), - strlen(xmlText), "VGAuthSamlAssertion"); - - parser.parse(in); - - xsecsize_t errorCount = parser.getErrorCount(); - if (errorCount > 0) { - Debug("Encountered %u errors while parsing SAML assertion.\n", - (unsigned int) errorCount); - return NULL; - } - - DOMDocument *doc = parser.getDocument(); - ASSERT(doc != NULL); - - return doc; -} - - -/* - ****************************************************************************** - * SAMLCheckSubject -- */ /** - * - * Extracts the name of the subject and enforces any conditions in - * SubjectConfirmation elements. - * Subjects are described in section 2.4 of the SAML Core specification. - * - * Example Subject XML: - * - * - * scott@example.org - * - * - * - * - * - * - * - * @param[in] doc The DOM representation of the SAML assertions. - * @param[in/out] token Information about the token to be populated. - * - * @return true if the conditions in at least one SubjectConfirmation is met, - * false otherwise. - * - ****************************************************************************** - */ - -static bool -SAMLCheckSubject(const DOMDocument *doc, - SAMLTokenData &token) -{ - const DOMElement *subject; - char *name = g_strdup_printf("%sSubject", - token.ns.c_str()); - subject = SAMLFindChildByName(doc->getDocumentElement(), name); - g_free(name); - - if (NULL == subject) { - // Should not happen, since this is required element in the schema. - Log("%s: Missing subject element!\n", __FUNCTION__); -// ASSERT(0); - return false; - } - - const DOMElement *nameID; - name = g_strdup_printf("%sNameID", token.ns.c_str()); - nameID = SAMLFindChildByName(subject, name); - g_free(name); - if (NULL == nameID) { - /* - * The schema allows BaseID, NameID, or EncryptedID. The library code - * for the SSO server only supports NameID. EncryptedID is really - * complicated (and we don't have decryption keys, so let's not - * support it for now. - */ - - Log("%s: No NameID element for the subject.\n", __FUNCTION__); - return false; - } - - token.subjectName = SAMLStringWrapper(nameID->getTextContent()).c_str(); - Debug("%s: subjectName: '%s'\n", __FUNCTION__, token.subjectName.c_str()); - - /* - * TODO: Investigate: NameID elements can have a NameQualifier attribute. - * This smells like a domain name, and we might want to include it with - * subject name (\subjectName). - */ - - /* - * Find all the SubjectConfirmation nodes and see if at least one can be - * verified. - */ - - name = g_strdup_printf("%sSubjectConfirmation", token.ns.c_str()); - XMLT scName(name); - g_free(name); - for (DOMElement *child = subject->getFirstElementChild(); child != NULL; - child = child->getNextElementSibling()) { - - if (!XMLString::equals(child->getNodeName(), scName.getUnicodeStr())) { - continue; - } - - const XMLCh *method = child->getAttribute(MAKE_UNICODE_STRING("Method")); - if ((NULL == method) || (0 == *method)) { - // Should not happen, since this is a required attribute. - ASSERT(0); - Debug("%s: Missing confirmation method.\n", __FUNCTION__); - continue; - } - - if (!XMLString::equals( - MAKE_UNICODE_STRING("urn:oasis:names:tc:SAML:2.0:cm:bearer"), - method)) { - Debug("%s: Non-bearer confirmation method in token", __FUNCTION__); - continue; - } - - const DOMElement *subjConfirmData; - name = g_strdup_printf("%sSubjectConfirmationData", token.ns.c_str()); - subjConfirmData = SAMLFindChildByName(child, name); - g_free(name); - if (NULL != subjConfirmData) { - if (!SAMLCheckTimeAttr(subjConfirmData, "NotBefore", true) || - !SAMLCheckTimeAttr(subjConfirmData, "NotOnOrAfter", false)) { - Warning("%s: subjConfirmData time check failed\n", __FUNCTION__); - continue; - } - - const XMLCh *recipient; - recipient = subjConfirmData->getAttribute( - MAKE_UNICODE_STRING("Recipient")); - /* - * getAttribute() returns a 0-length string, not NULL, if it can't - * find what it wants. - */ - if ((0 != XMLString::stringLen(recipient)) && - !SAMLCheckAudience(recipient)) { - Debug("%s: failed recipient check\n", __FUNCTION__); - continue; - } - } - - return true; - } - - Debug("%s: Could not verify using any SubjectConfirmation elements\n", - __FUNCTION__); - return false; -} - - -/* - ****************************************************************************** - * SAMLCheckConditions -- */ /** - * - * Enforces conditions specified by the "saml:Conditions" element - * under the root element. - * Conditions are described in section 2.5 of the SAML Core specification. - * - * Example Conditions XML: - * - * - * https://sp.example.com/SAML2 - * - * - * - * @param[in] doc The DOM representation of the SAML assertions. - * - * @return true if the conditions are met; false otherwise. - * - ****************************************************************************** - */ - -static bool -SAMLCheckConditions(const DOMDocument *doc, - SAMLTokenData &token) -{ - /* - * There should be at most one Conditions element and the schema checking - * done by the parser should enforce that. - */ - char *name = g_strdup_printf("%sConditions", token.ns.c_str()); - const DOMElement *conditions = SAMLFindChildByName(doc->getDocumentElement(), - name); - g_free(name); - if (NULL == conditions) { - // Conditions are optional. - return true; - } - - if (!SAMLCheckTimeAttr(conditions, "NotBefore", true) || - !SAMLCheckTimeAttr(conditions, "NotOnOrAfter", false)) { - return false; - } - - /* - * is a generic element, intended as an extension point. - * We don't know about any. According to the general processng rules, if - * we find a condition we don't know about, the result of the validation - * is "indeterminate" and we should reject the assertion. - */ - name = g_strdup_printf("%sCondition", token.ns.c_str()); - if (SAMLFindChildByName(conditions, name) != NULL) { - Log("%s: Unrecognized condition found!\n", __FUNCTION__); - g_free(name); - return false; - } - g_free(name); - - /* - * defines a set a URIs that describe what - * audience the assertioned is addressed to or intended for. - * But it's very generic. From the spec (section 2.5.1.4): - * A URI reference that identifies an intended audience. The URI - * reference MAY identify a document that describes the terms and - * conditions of audience membership. It MAY also contain the unique - * identifier URI from a SAML name identifier that describes a system - * entity. - * Some searching online shows people using http:/// as the - * URI, but let's wait until we get some feedback from the SSO team. - * TODO: Validate it using SAMLCheckAudience(). - */ - - /* - * element is specified to disallow caching. We don't - * cache, so it doesn't affect out validation. - * However, we need to communicate it to clients so they do not cache. - */ - name = g_strdup_printf("%sOneTimeUse", token.ns.c_str()); - token.oneTimeUse = (SAMLFindChildByName(conditions, name) - != NULL); - g_free(name); - - /* - * only applies if a service wants to make their own - * assertions based on a SAML assertion. That should not apply here. - */ - - return true; -} - - -/* - ****************************************************************************** - * SAMLCheckTimeAttr -- */ /** - * - * Checks that the given attribute with the given name is a timestamp and - * compares it against the current time. - * - * @param[in] elem The element containing the attribute. - * @param[in] attrName The name of the attribute. - * @param[in] notBefore Whether the condition given by the attribute - * should be in the past or 'now' (true). - * - ****************************************************************************** - */ - -static bool -SAMLCheckTimeAttr(const DOMElement *elem, - const char *attrName, - bool notBefore) -{ - const XMLCh *timeAttr = elem->getAttribute(MAKE_UNICODE_STRING(attrName)); - if ((NULL == timeAttr) || (0 == *timeAttr)) { - /* - * The presence of all time restrictions in SAML are optional, so if - * the attribute is not present, that is fine. - */ - return true; - } - - SAMLStringWrapper timeStr(timeAttr); - GTimeVal attrTime; - - if (!g_time_val_from_iso8601(timeStr.c_str(), &attrTime)) { - Log("%s: Could not parse %s value (%s).\n", __FUNCTION__, attrName, - timeStr.c_str()); - return false; - } - - GTimeVal now; - g_get_current_time(&now); - - glong diff; - - /* - * Check the difference, doing the math so that a positive - * value is bad. Ignore the micros since we're letting clock - * skew add a fudge-factor. - */ - if (notBefore) { - // expect time <= now - diff = attrTime.tv_sec - now.tv_sec; - } else { - // expect now <= time - diff = now.tv_sec - attrTime.tv_sec; - } - - /* - * A negative value is fine, a postive value - * greater than the clock skew range is bad. - */ - if (diff > clockSkewAdjustment) { - Warning("%s: FAILED SAML assertion (timeStamp %s, delta %d) %s.\n", - __FUNCTION__, timeStr.c_str(), (int) diff, - notBefore ? "is not yet valid" : "has expired"); - return false; - } - - return true; -} - - -/* - ****************************************************************************** - * SAMLCheckAudience -- */ /** - * - * Checks whether the given audience URI refers to this machine. - * - * @param[in] audience An audience URI that a token is targetted for. - * - * @return True if the audience URI refers to this machine, false otherwise. - * - ****************************************************************************** - */ - -static bool -SAMLCheckAudience(const XMLCh *audience) -{ - bool ret; - - /* - * XXX This should be much better. Ideally it should check that it refers - * to the hostname of a URL or matches some kind of URN. Also, this is - * where the VC UUID can be used when running in a VM. - * We should accept: - * URL: ://[/stuff] - * URN: urn:vmware:vgauth:::[vgauth_client_app_name] - * Glib has a basic URL and we should use it. - * TODO: Need a RpcIn call into the VMX to get the VC UUID, since it is not - * currently exposed. (Could be NamespaceDB, but then need to make a separate - * workflow for pushing the VC UUIDs out to VMs.) - */ - - ret = strstr(SAMLStringWrapper(audience).c_str(), - g_get_host_name()) != NULL; - Debug("%s: audience check: token: '%s', host: '%s' ? %d\n", - __FUNCTION__, - SAMLStringWrapper(audience).c_str(), - g_get_host_name(), ret); - return ret; -} - - -/* - ****************************************************************************** - * SAMLCheckSignature -- */ /** - * - * Finds the signature in the SAML assertion, then extracts the X509 - * from that, then checks that the signature is valid. - * - * @param[in] doc The document of which to check the signature. - * @param[in] hostVerified If true, skip signature verification. - * @param[out] certs The base64 encoded certificates present in the - * signature. - * - * @return true if the signature if valid, false otherwise. - * - ****************************************************************************** - */ - -static bool -SAMLCheckSignature(DOMDocument *doc, - gboolean hostVerified, - vector &certs) -{ - DOMElement *sigElem = SAMLFindChildByName(doc->getDocumentElement(), - "ds:Signature"); - if (NULL == sigElem) { - Warning("%s: No top level signature found.\n", __FUNCTION__); - return false; - } - - XSECEnv secEnv(doc); - - auto_ptr keyInfo = SAMLFindKey(secEnv, sigElem); - if (keyInfo.get() == NULL) { - Warning("%s: No X509 data found as part of the signature.\n", - __FUNCTION__); - return false; - } - - if (keyInfo->getCertificateListSize() == 0) { - Warning("%s: No X509 certificates found in the signature\n", - __FUNCTION__); - return false; - } - if (hostVerified) { - Debug("hostVerified is set, skipping signtaure check"); - } else { - - const XSECCryptoX509 *x509 = keyInfo->getCertificateCryptoItem(0); - ASSERT(NULL != x509); - - XSECProvider prov; - DSIGSignature *sig = prov.newSignatureFromDOM(doc, sigElem); - - sig->load(); - sig->setSigningKey(x509->clonePublicKey()); - - if (!SAMLCheckReference(doc, sig)) { - return false; - } - - if (!sig->verify()) { - Warning("%s: Signature check failed: %s.\n", __FUNCTION__, - SAMLStringWrapper(sig->getErrMsgs()).c_str()); - return false; - } - - } - for (int i = 0; i < keyInfo->getCertificateListSize(); i++) { - const XSECCryptoX509 *cert = keyInfo->getCertificateCryptoItem(i); - certs.push_back(string(cert->getDEREncodingSB().rawCharBuffer())); - } - - return true; -} - - -/* - ****************************************************************************** - * SAMLCheckReference -- */ /** - * - * Checks that the given signature refers to (and thus was computed over) - * the root element of the document. This ensures that the entire document - * is protected/endorsed by the signature. - * See the SAML Core specification, section 5.4.2. - * - * @param[in] doc The document in which contains the signature. - * @param[in] sig The signature - * - * @return true if the signature refers to the whole document, or false - * otherwise. - * - ****************************************************************************** - */ - -static bool -SAMLCheckReference(const DOMDocument *doc, - DSIGSignature *sig) -{ - DOMElement *rootElem = doc->getDocumentElement(); - - const XMLCh *id = rootElem->getAttribute(MAKE_UNICODE_STRING("ID")); - if (NULL == id) { - Debug("%s: NULL ID attribute.\n", __FUNCTION__); - return false; - } - - XMLSize_t idLen = XMLString::stringLen(id); - if (0 == idLen) { - Debug("%s: Root element has no or an empty ID attribute.\n", - __FUNCTION__); - return false; - } - - /* - * At least one reference should contain a URI that refers to the root - * element. To do so, that URI should be "#" followed by the value of - * the ID element of the root node; for example if the ID is "SAML" the - * URI must be "#SAML". - * - * TODO: The vmacore implementation of SAML parsing, used by clients - * validating tokens, allows for multiple references and considers if - * at least one matches. However, the SAML spec (section 5.4.2) requires - * that there be only one reference element in the signature. Currently - * we follow the vmacore behavior. - */ - - XMLT uriPrefix("#"); - XMLSize_t prefixLen = XMLString::stringLen(uriPrefix.getUnicodeStr()); - - DSIGReferenceList *references = sig->getReferenceList(); - DSIGReferenceList::size_type numReferences = references->getSize(); - for (DSIGReferenceList::size_type i = 0; i < numReferences; i++) { - DSIGReference *ref = references->item(i); - const XMLCh *uri = ref->getURI(); - - if (uri != NULL && - XMLString::startsWith(uri, uriPrefix.getUnicodeStr()) && - XMLString::equals(id, uri + prefixLen)) { - return true; - } - } - - Debug("%s: No matching reference found in the signature for ID '%s'.\n", - __FUNCTION__, SAMLStringWrapper(id).c_str()); - return false; -} - - -/* - ****************************************************************************** - * SAMLFindChildByName -- */ /** - * - * Finds the first element that is a child of the given element which - * matches the given node name. - * - * TODO: Investigate using getLocalName() and getNamespaceURI() to - * identify the child, since in "ds:Signature" "ds" is an alias to as longer - * URI, and that URI should be used instead (it's more stable). - * - * @param[in] elem The element to search the children of. - * @param[in] name The name of the child element - * - * @return A pointer to the DOMElement matching the name, or NULL if - * no such element is found. - * - ****************************************************************************** - */ - -static DOMElement * -SAMLFindChildByName(const DOMElement *elem, - const char *name) -{ - XMLT sigNodeName(name); - DOMElement *childElem; - - for (childElem = elem->getFirstElementChild(); - childElem != NULL; childElem = childElem->getNextElementSibling()) { - if (XMLString::equals(childElem->getNodeName(), - sigNodeName.getUnicodeStr())) { - break; - } - } - - return childElem; -} - - -/* - ****************************************************************************** - * SAMLFindKey -- */ /** - * - * Finds the first ds:X509Data element under the given ds:Signature element. - * - * @param[in] secEnv A XSEC environment to create the object from. - * @param[in] sigElem The root element of the signuture. - * - * @return A pointer to a DSIGKeyInfoX509 object, which must be freed using - * operator delete, or NULL if no ds:X509Data element is found. - * - ****************************************************************************** - */ - -static auto_ptr -SAMLFindKey(const XSECEnv &secEnv, - const DOMElement *sigElem) -{ - DOMNodeList *keyInfos = - sigElem->getElementsByTagName(MAKE_UNICODE_STRING("ds:X509Data")); - - if (keyInfos->getLength() == 0) { - return auto_ptr(NULL); - } - - auto_ptr keyInfo(new DSIGKeyInfoX509(&secEnv, - keyInfos->item(0))); - - keyInfo->load(); - - return keyInfo; -} diff --git a/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c b/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c index 14cba1b5b..0cc4edbb4 100644 --- a/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c +++ b/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c @@ -48,6 +48,33 @@ #include "certverify.h" #include "vmxlog.h" +/* + * XXX + * + * Optimization idea: stash a hash (SHA512) of a valid token, and bypass + * the full assertion process when we see that token again. The expiration + * date of the token must also be saved off (and beware the time skew issue). + * + * Note that there's some extra complexity here: + * + * 1 - AddAlias sets up a cert/user mapping + * 2 - a SAML token is used (and cached) using this cert/user combo + * 3 - RemoveAlias removes the combo + * 4 - the cached token still works + * + * So the cache should only bypass the token validation, not the certificate + * check in ServiceVerifyAndCheckTrustCertChainForSubject() + * + * Also TBD is how much this buys us in the real world. With short + * token lifetimes, its less interesting. Its also possible that + * it will have no measureable affect because the token verification + * will be lost in the noise of the API plumbing from VC->hostd->VMX->tools. + * + * The security folks have signed off on this, so long as we store only + * in memory. + * + */ + static int gClockSkewAdjustment = VGAUTH_PREF_DEFAULT_CLOCK_SKEW_SECS; static xmlSchemaPtr gParsedSchemas = NULL; static xmlSchemaValidCtxtPtr gSchemaValidateCtx = NULL; @@ -1316,9 +1343,9 @@ VerifySignature(xmlDocPtr doc, /* * Get the cert chain from the token. * - * Unlike xml-security-c, xmlsec1 wants to validate the cert - * chain in the token so it needs the full chain, not just - * the public key from the first cert. + * xmlsec1 wants to validate the cert chain in the token + * so it needs the full chain, not just the public key from + * the first cert. * * Also save it off for later use by the alias store check. */ @@ -1378,8 +1405,8 @@ VerifySignature(xmlDocPtr doc, } /* - * The xml-security-c verifies the Reference explicitly; this - * isn't needed for xmlsec1 because the library does it. + * No need to verify the Reference explicitly because the + * xmlsec1 library takes care of it. */ /* diff --git a/open-vm-tools/vgauth/serviceImpl/samlInt.hpp b/open-vm-tools/vgauth/serviceImpl/samlInt.hpp deleted file mode 100644 index 19f26f374..000000000 --- a/open-vm-tools/vgauth/serviceImpl/samlInt.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/********************************************************* - * Copyright (C) 2011-2016,2023 VMware, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation version 2.1 and no later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - *********************************************************/ - -/** - * @file samlInt.hpp - * - * Functions that only need to be used within the SAML module or - * for testing thereof. - */ - -#ifndef _SAMLINT_H_ -#define _SAMLINT_H_ - -#include -#include - -#include - -#include - -#include "VGAuthError.h" - - -using namespace std; - -#ifdef XERCES_CPP_NAMESPACE_USE -XERCES_CPP_NAMESPACE_USE -#endif - - -/** - * Inherit from this class to disallow copy-construction and - * assignment. (Similar to boost::noncopyable) - */ - -class Noncopyable { -protected: - Noncopyable() - { - } - -private: - // Disallow copy-construction, assignment. - Noncopyable(const Noncopyable &); - const Noncopyable& operator=(const Noncopyable &); -}; - -/** - * A simple wrapper to convert Xerces's XMLCh strings to UTF-8, and manage - * the memory for the converted string. Instances of this class are immutable. - */ - -class SAMLStringWrapper : public Noncopyable { -public: - SAMLStringWrapper(const XMLCh *str) : - m_str(XMLString::transcode(str)) - { - } - - ~SAMLStringWrapper() - { - XMLString::release(const_cast(&m_str)); - } - - const char * - c_str() const - { - return m_str; - } - -private: - const char *m_str; -}; - -/** - * Wrapper class for strings allocated by GLib. The object takes ownership of - * the string's memory. - */ - -class SAMLGlibString { -public: - SAMLGlibString(gchar *str) : - m_str(str) - { - } - - SAMLGlibString(const SAMLGlibString &s) : - m_str(g_strdup(s.m_str)) - { - } - - ~SAMLGlibString() - { - g_free(const_cast(m_str)); - } - -const char * - c_str() const - { - return m_str; - } - -private: - SAMLGlibString &operator=(const SAMLGlibString &); // immuatable - - const gchar *m_str; -}; - -/* - * Holds data extracted from a SAML token. - */ -struct SAMLTokenData { - string subjectName; - vector issuerCerts; - bool oneTimeUse; - bool isSSOToken; // set if token came from VMware SSO server - string ns; -}; - - -auto_ptr SAMLCreateAndPopulateGrammarPool(); - -VGAuthError SAMLVerifyAssertion(const char *xmlText, - gboolean hostVerified, - SAMLTokenData &token, - vector &certs); -#endif // ifndef _SAMLINT_H_