/*
* State of a single asynch startProgram.
+ *
+ * On Windows, keep the user's token and profile HANDLEs around
+ * so the profile isn't unloaded until the program exits.
*/
typedef struct VixToolsStartProgramState {
ProcMgr_AsyncProc *procState;
+#if defined(_WIN32) && SUPPORT_VGAUTH
+ HANDLE hToken;
+ HANDLE hProfile;
+#endif
+
void *eventQueue;
} VixToolsStartProgramState;
VGAuthError TheVGAuthContext(VGAuthContext **ctx);
+#ifdef _WIN32
+static void GuestAuthUnloadUserProfileAndToken(HANDLE hToken, HANDLE hProfile);
+#endif
+
#endif
Bool envBlockFromMalloc = TRUE;
#endif
GSource *timer;
+#if defined(_WIN32) && SUPPORT_VGAUTH
+ HANDLE hToken = INVALID_HANDLE_VALUE;
+ HANDLE hProfile = INVALID_HANDLE_VALUE;
+ VGAuthError vgErr;
+ VGAuthContext *ctx;
+#endif
/*
* Initialize this here so we can call free on its member variables in abort
procArgs.envp = (char **)envVars;
#endif
+#if defined(_WIN32) && SUPPORT_VGAUTH
+ /*
+ * Special case profile handling for StartProgram. It should stay loaded
+ * until the program exits, so copy the profile and user handles for
+ * later cleanup, and clobber the profile handle so that it's not unloaded
+ * when the impersonation ends.
+ *
+ * Only do this when we've actually impersonated; its not
+ * needed when impersonation isn't done (eg vmusr or SYSTEM bypass).
+ */
+ if (GuestAuthEnabled() && PROCESS_CREATOR_USER_TOKEN != userToken) {
+ vgErr = TheVGAuthContext(&ctx);
+ if (VGAUTH_FAILED(vgErr)) {
+ err = VixToolsTranslateVGAuthError(vgErr);
+ g_warning("%s: Couldn't get the vgauth context\n", __FUNCTION__);
+ goto abort;
+ }
+
+ vgErr = VGAuth_UserHandleAccessToken(ctx, currentUserHandle, &hToken);
+ if (VGAUTH_FAILED(vgErr)) {
+ err = VixToolsTranslateVGAuthError(vgErr);
+ g_warning("%s: Failed to get user token\n", __FUNCTION__);
+ goto abort;
+ }
+ vgErr = VGAuth_UserHandleGetUserProfile(ctx, currentUserHandle,
+ &hProfile);
+ if (VGAUTH_FAILED(vgErr)) {
+ err = VixToolsTranslateVGAuthError(vgErr);
+ g_warning("%s: Failed to get user profile\n", __FUNCTION__);
+ CloseHandle(hToken);
+ goto abort;
+ }
+ }
+ asyncState->hToken = hToken;
+ asyncState->hProfile = hProfile;
+#endif
+
asyncState->procState = ProcMgr_ExecAsync(fullCommandLine, &procArgs);
#if defined(_WIN32)
g_debug("%s: started '%s', pid %"FMT64"d\n",
__FUNCTION__, fullCommandLine, *pid);
+#if defined(_WIN32) && SUPPORT_VGAUTH
+ /*
+ * Clobber the profile handle before un-impersonation.
+ */
+ if (GuestAuthEnabled() && PROCESS_CREATOR_USER_TOKEN != userToken) {
+ vgErr = VGAuth_UserHandleSetUserProfile(ctx, currentUserHandle,
+ INVALID_HANDLE_VALUE);
+ if (VGAUTH_FAILED(vgErr)) {
+ err = VixToolsTranslateVGAuthError(vgErr);
+ g_warning("%s: Failed to clobber user profile\n", __FUNCTION__);
+ // VGAuth_EndImpersonation will take care of profile, close hToken
+ CloseHandle(asyncState->hToken);
+ asyncState->hToken = INVALID_HANDLE_VALUE;
+ asyncState->hProfile = INVALID_HANDLE_VALUE;
+ goto abort;
+ }
+ }
+#endif
+
/*
* Start a periodic procedure to check the app periodically
*/
*/
asyncState = NULL;
+
abort:
free(tempCommandLine);
free(fullCommandLine);
*
*-----------------------------------------------------------------------------
*/
+
static void
VixToolsUpdateStartedProgramList(VixToolsStartedProgramState *state) // IN
{
spList->endTime = state->endTime;
spList->isRunning = FALSE;
+ g_debug("%s: started program '%s' has completed, exitCode %d\n",
+ __FUNCTION__, spList->fullCommandLine, spList->exitCode);
+
/*
* Don't let the procState be free'd on Windows to
* keep OS from reusing the pid. We need to free
*userToken = PROCESS_CREATOR_USER_TOKEN;
gImpersonatedUsername = Util_SafeStrdup(unobfuscatedUserName);
+ g_debug("%s: allowing interactive mode for user '%s'\n",
+ __FUNCTION__, gImpersonatedUsername);
+
goto abort;
} else {
/*
if (NULL == asyncState) {
return;
}
+#if defined(_WIN32) && SUPPORT_VGAUTH
+ /*
+ * Unload the user profile if saved.
+ */
+ if (asyncState->hProfile != INVALID_HANDLE_VALUE &&
+ asyncState->hToken != INVALID_HANDLE_VALUE) {
+ GuestAuthUnloadUserProfileAndToken(asyncState->hToken,
+ asyncState->hProfile);
+ }
+#endif
free(asyncState);
} // VixToolsFreeStartProgramState
*ctx = vgaCtx;
return vgaCode;
}
-#endif
+
+
+#ifdef _WIN32
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * GuestAuthUnloadUserProfileAndToken --
+ *
+ * Unload user profile and close user token.
+ *
+ * Helper to handle StartProgram cleanup.
+ *
+ * Return value:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+GuestAuthUnloadUserProfileAndToken(HANDLE hToken,
+ HANDLE hProfile)
+{
+ if (GuestAuthEnabled()) {
+ g_debug("%s: special-case profile unload %p\n", __FUNCTION__, hProfile);
+ if (!UnloadUserProfile(hToken, hProfile)) {
+ g_warning("%s: UnloadUserProfile() failed %d\n",
+ __FUNCTION__, GetLastError());
+ }
+ CloseHandle(hToken);
+ }
+}
+#endif // _WIN32
+
+#endif // SUPPORT_VGAUTH
+