From: Oliver Kurth Date: Fri, 15 Sep 2017 18:22:55 +0000 (-0700) Subject: Allow SAML authn to bypass impersonation if the user is unchanged X-Git-Tag: stable-10.2.0~616 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=622e55c0101f13c8f8da41fa18b7a25c0a05d61e;p=thirdparty%2Fopen-vm-tools.git Allow SAML authn to bypass impersonation if the user is unchanged vmwsu can't create an impersonation token for SYSTEM since its not a 'real' account. So bypass the impersonation phase since toolsd is already running as SYSTEM. --- diff --git a/open-vm-tools/services/plugins/vix/vixTools.c b/open-vm-tools/services/plugins/vix/vixTools.c index 114dfd167..54b02398a 100644 --- a/open-vm-tools/services/plugins/vix/vixTools.c +++ b/open-vm-tools/services/plugins/vix/vixTools.c @@ -140,6 +140,12 @@ #define SUPPORT_VGAUTH 0 #endif +#ifdef _WIN32 +/* + * vmwsu can't generate an impersonation token for local SYSTEM. + */ +#define ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS 1 +#endif #if SUPPORT_VGAUTH #include "VGAuthCommon.h" @@ -155,6 +161,19 @@ static gboolean gSupportVGAuth = USE_VGAUTH_DEFAULT; static gboolean QueryVGAuthConfig(GKeyFile *confDictRef); +#if ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS +static gchar *gCurrentUsername = NULL; + +#define VIXTOOLS_CONFIG_ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS \ + "allowLocalSystemImpersonationBypass" +/* + * This isn't on by default because it won't leave a complete + * audit trail. + */ +#define ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS_DEFAULT FALSE + +#endif + /* * XXX * @@ -697,6 +716,14 @@ VixTools_Initialize(Bool thisProcessRunsAsRootParam, VixError err = VIX_OK; #if SUPPORT_VGAUTH ToolsAppCtx *ctx = (ToolsAppCtx *) clientData; +#if ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS + if (!gCurrentUsername) { + gCurrentUsername = VixToolsGetCurrentUsername(); + ASSERT(gCurrentUsername); + g_message("%s: Toolsd running as user '%s'\n", + __FUNCTION__, gCurrentUsername); + } +#endif #endif /* @@ -7928,6 +7955,11 @@ VixToolsUnimpersonateUser(void *userToken) gImpersonatedUsername = NULL; #if SUPPORT_VGAUTH +#if ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS + if (PROCESS_CREATOR_USER_TOKEN == userToken) { + g_debug("%s: Faking unimpersonate\n", __FUNCTION__); + } +#endif if (NULL != currentUserHandle) { GuestAuthUnimpersonate(); return; @@ -11438,11 +11470,107 @@ GuestAuthSAMLAuthenticateAndImpersonate( 0, NULL, &newHandle); +#if ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS + /* + * Special support for local SYSTEM account. + * + * If validation fails, try again without token + * creation, and if it passes, fake the impersonation. + */ + + // normal case worked + if (!VGAUTH_FAILED(vgErr)) { + goto impersonate; + } + + /* + * If the config is off, bypass the special-case. + */ + if (!VixTools_ConfigGetBoolean(gConfDictRef, + VIX_TOOLS_CONFIG_API_GROUPNAME, + VIXTOOLS_CONFIG_ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS, + ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS_DEFAULT)) { + g_debug("%s: SAML authn failed, %s not set, skipping local SYSTEM check", + __FUNCTION__, + VIXTOOLS_CONFIG_ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS); + err = VixToolsTranslateVGAuthError(vgErr); + goto done; + } + + /* + * VGAUTH_E_FAIL will be returned if token creation fails. + */ + if (vgErr != VGAUTH_E_FAIL) { + err = VixToolsTranslateVGAuthError(vgErr); + goto done; + } else { + VGAuthExtraParams extraParams[1]; + VGAuthError vgErr2; + + extraParams[0].name = VGAUTH_PARAM_VALIDATE_INFO_ONLY; + extraParams[0].value = VGAUTH_PARAM_VALUE_TRUE; + + vgErr2 = VGAuth_ValidateSamlBearerToken(ctx, + token, + username, + 1, + extraParams, + &newHandle); + // if it passes with VALIDATE_ONLY, see if its the current user (SYSTEM) + if (vgErr2 == VGAUTH_E_OK) { + gchar *tokenUser = NULL; + + vgErr2 = VGAuth_UserHandleUsername(ctx, newHandle, &tokenUser); + if (VGAUTH_FAILED(vgErr2)) { + g_warning("%s: VGAuth_UserHandleUsername() failed\n", __FUNCTION__); + err = VixToolsTranslateVGAuthError(vgErr2); + goto done; + } + + g_debug("%s: VGAuth_ValidateSamlBearerToken() with " + "VGAUTH_PARAM_VALIDATE_INFO_ONLY: user is %s, " + "toolsd user is %s\n", + __FUNCTION__, tokenUser, gCurrentUsername); + + /* + * If VGAUTH_PARAM_VALIDATE_INFO_ONLY passed, and the + * username matches, bypass impersonation. Be sure + * to do a case-less comparison. + */ + if (Unicode_CompareIgnoreCase(tokenUser, gCurrentUsername) == 0) { + g_message("%s: User '%s' matched; bypassing impersonation\n", + __FUNCTION__, gCurrentUsername); + + // set the impersonation token to the magic value + *userToken = PROCESS_CREATOR_USER_TOKEN; + gImpersonatedUsername = Util_SafeStrdup("_CONSOLE_USER_NAME_"); + currentUserHandle = newHandle; + err = VIX_OK; + } else { + g_message("%s: User '%s' mismatch with process user '%s'\n", + __FUNCTION__, tokenUser, gCurrentUsername); + // use original error code + err = VixToolsTranslateVGAuthError(vgErr); + } + VGAuth_FreeBuffer(tokenUser); + goto done; + + } else { + // use original error code + err = VixToolsTranslateVGAuthError(vgErr); + goto done; + } + } +#else if (VGAUTH_FAILED(vgErr)) { err = VixToolsTranslateVGAuthError(vgErr); goto done; } +#endif +#if ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS +impersonate: +#endif vgErr = VGAuth_Impersonate(ctx, newHandle, 0, NULL); if (VGAUTH_FAILED(vgErr)) { err = VixToolsTranslateVGAuthError(vgErr); @@ -11496,6 +11624,7 @@ GuestAuthUnimpersonate(void) VGAuthError vgErr = TheVGAuthContext(&ctx); ASSERT(vgErr == VGAUTH_E_OK); + vgErr = VGAuth_EndImpersonation(ctx); ASSERT(vgErr == VGAUTH_E_OK); @@ -11624,9 +11753,9 @@ TheVGAuthContext(VGAuthContext **ctx) // OUT VGAuthError vgaCode = VGAUTH_E_OK; /* - * XXX This needs to handle errors better -- if the service gets - * reset, the context will point to junk and anything using it will - * fail. + * XXX This needs to handle errors better -- if the VGAuthService + * service gets reset, the context will point to junk and anything + * using it will fail. * * Maybe add a no-op API here to poke it? Or make the underlying * VGAuth code smarter. diff --git a/open-vm-tools/services/plugins/vix/vixToolsInt.h b/open-vm-tools/services/plugins/vix/vixToolsInt.h index 27986500f..fc86953bb 100644 --- a/open-vm-tools/services/plugins/vix/vixToolsInt.h +++ b/open-vm-tools/services/plugins/vix/vixToolsInt.h @@ -187,6 +187,8 @@ VixError VixToolsListRegValuesImpl(VixCommandRequestHeader *requestMsg, VixError VixToolsDeleteRegValueImpl(VixCommandRequestHeader *requestMsg); +gchar *VixToolsGetCurrentUsername(void); + #endif // _WIN32 #ifdef VMX86_DEVEL