/* returns TRUE if the user profile was unloaded; otherwise, FALSE. Also ensures the profile information is cleaned out. */ BOOL OwnerProfile::unloadProfile () { dprintf ( D_FULLDEBUG, "In OwnerProfile::unloadProfile()\n" ); priv_state priv; BOOL profile_unloaded = FALSE, ok = FALSE; __try { /* we must do the following as */ priv = set_condor_priv (); /* unload the current profile */ profile_unloaded = UnloadUserProfile ( user_token_, user_profile_.hProfile ); dprintf ( D_FULLDEBUG, "OwnerProfile::unloadProfile: Unloading %s's " "profile %s. (last-error = %u)\n", user_name_, profile_unloaded ? "succeeded" : "failed", profile_unloaded ? 0 : GetLastError () ); if ( !profile_unloaded ) { __leave; } /* if we got here then all is well in the universe */ ok = TRUE; } __finally { /* we use SecureZeroMemory() here because it has a very desirable property: it will never be optimized away, as its cousin ZeroMemory() might be. This is of great interest to us, as the state of the profile structure greatly influences the behaviour of this class. */ if ( ok ) { SecureZeroMemory ( &user_profile_, sizeof ( PROFILEINFO ) ); } /* return to previous privilege level */ set_priv ( priv ); } return ok; }
ActivePet::~ActivePet() { m_files->ignore(m_requestFolderPath, m_dispatcher); // Kill any stray processes. if (!TerminateJobObject(m_job.get(), -1)) { printf("TerminateJobObject() failed: %d", GetLastError()); } // TODO: Change this algorithm for transient accounts. std::for_each(m_syncers.begin(), m_syncers.end(), delete_element<Syncer*>()); RegKey editables = RegKey::HKCU.open(Constants::registryPets() + L"\\" + m_petname + L"\\" + Constants::editables()); editables.removeSubKeys(); // Unload the profile. UnloadUserProfile(m_session.get(), m_profile); // Undo the changes to the winsta0 and desktop DACLs. auto_buffer<PSID> logon_sid = GetLogonSID(m_session.get()); if (NULL == logon_sid.get()) { return; } auto_close<HWINSTA, &::CloseWindowStation> winsta0(OpenWindowStation(L"winsta0", FALSE, READ_CONTROL | WRITE_DAC)); if (NULL == winsta0.get()) { printf("OpenWindowStation() failed: %d", GetLastError()); return; } if (!RemoveAceFromWindowStation(winsta0.get(), logon_sid.get())) { printf("RemoveAceFromWindowStation() failed: %d", GetLastError()); return; } auto_close<HDESK, &::CloseDesktop> desktop(OpenDesktop(L"default", 0, FALSE, READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS)); if (NULL == desktop.get()) { printf("OpenDesktop() failed: %d", GetLastError()); return; } if (!RemoveAceFromDesktop(desktop.get(), logon_sid.get())) { printf("AddAceToDesktop() failed: %d", GetLastError()); return; } }
Result<ExitCode> ProcessAsUser::Run(const Settings& settings, ProcessTracker& processTracker) const { Trace trace(settings.GetLogLevel()); trace < L"ProcessAsUser::Attempt to log a user on to the local computer"; StringBuffer userName(settings.GetUserName()); StringBuffer domain(settings.GetDomain()); StringBuffer password(settings.GetPassword()); StringBuffer workingDirectory(settings.GetWorkingDirectory()); StringBuffer commandLine(settings.GetCommandLine()); SecurityManager securityManager; auto setPrivilegesResult = securityManager.SetPrivileges(trace, { SE_TCB_NAME, SE_ASSIGNPRIMARYTOKEN_NAME }, true); if(setPrivilegesResult.HasError()) { return setPrivilegesResult.GetError(); } auto newUserSecurityTokenHandle = Handle(L"New user security token"); unsigned long logonTypeCount = sizeof(allLogonTypes) / sizeof(allLogonTypes[0]); for (unsigned long logonTypeIndex = 0; logonTypeIndex < logonTypeCount; logonTypeIndex++) { auto logonType = allLogonTypes[logonTypeIndex]; trace < L"::LogonUser using logon type "; switch (logonType) { case LOGON32_LOGON_INTERACTIVE: trace << L"LOGON32_LOGON_INTERACTIVE"; break; case LOGON32_LOGON_NETWORK: trace << L"LOGON32_LOGON_NETWORK"; break; case LOGON32_LOGON_BATCH: trace << L"LOGON32_LOGON_BATCH"; break; case LOGON32_LOGON_SERVICE: trace << L"LOGON32_LOGON_SERVICE"; break; } if (LogonUser( userName.GetPointer(), domain.GetPointer(), password.GetPointer(), logonType, LOGON32_PROVIDER_DEFAULT, &newUserSecurityTokenHandle)) { break; } auto error = Error(L"LogonUser"); trace << L" - "; trace << error.GetDescription(); if(logonTypeIndex == logonTypeCount -1) { return error; } } trace < L"ProcessAsUser::InitializeConsoleRedirection a new security descriptor"; trace < L"::InitializeSecurityDescriptor"; SECURITY_DESCRIPTOR securityDescriptor = {}; if (!InitializeSecurityDescriptor( &securityDescriptor, SECURITY_DESCRIPTOR_REVISION)) { return Error(L"InitializeSecurityDescriptor"); } trace < L"::SetSecurityDescriptorDacl"; if (!SetSecurityDescriptorDacl( &securityDescriptor, true, nullptr, false)) { return Error(L"SetSecurityDescriptorDacl"); } trace < L"ProcessAsUser::Creates a new access primary token that duplicates new process's token"; auto primaryNewUserSecurityTokenHandle = Handle(L"Primary new user security token"); SECURITY_ATTRIBUTES processSecAttributes = {}; processSecAttributes.lpSecurityDescriptor = &securityDescriptor; processSecAttributes.nLength = sizeof(SECURITY_DESCRIPTOR); processSecAttributes.bInheritHandle = true; trace < L"::DuplicateTokenEx"; if (!DuplicateTokenEx( newUserSecurityTokenHandle, 0, // MAXIMUM_ALLOWED &processSecAttributes, SecurityImpersonation, TokenPrimary, &primaryNewUserSecurityTokenHandle)) { return Error(L"DuplicateTokenEx"); } SECURITY_ATTRIBUTES threadSecAttributes = {}; threadSecAttributes.lpSecurityDescriptor = nullptr; threadSecAttributes.nLength = 0; threadSecAttributes.bInheritHandle = false; STARTUPINFO startupInfo = {}; trace < L"ProcessTracker::InitializeConsoleRedirection"; auto error = processTracker.InitializeConsoleRedirection(processSecAttributes, startupInfo); if(error.HasError()) { return Result<ExitCode>(error.GetError()); } trace < L"::LoadUserProfile"; PROFILEINFO profileInfo = {}; profileInfo.dwSize = sizeof(PROFILEINFO); profileInfo.lpUserName = userName.GetPointer(); if (!LoadUserProfile(primaryNewUserSecurityTokenHandle, &profileInfo)) { return Error(L"LoadUserProfile"); } auto newProcessEnvironmentResult = GetEnvironment(settings, primaryNewUserSecurityTokenHandle, settings.GetInheritanceMode(), trace); if (newProcessEnvironmentResult.HasError()) { UnloadUserProfile(primaryNewUserSecurityTokenHandle, profileInfo.hProfile); return Result<ExitCode>(newProcessEnvironmentResult.GetError()); } auto setIntegrityLevelResult = securityManager.SetIntegrityLevel(settings.GetIntegrityLevel(), primaryNewUserSecurityTokenHandle, trace); if (setIntegrityLevelResult.HasError()) { return Result<ExitCode>(setIntegrityLevelResult.GetError()); } trace < L"ProcessAsUser::Create a new process and its primary thread. The new process runs in the security context of the user represented by the specified token."; PROCESS_INFORMATION processInformation = {}; startupInfo.dwFlags = STARTF_USESHOWWINDOW; startupInfo.wShowWindow = ShowModeConverter::ToShowWindowFlag(settings.GetShowMode()); auto cmdLine = settings.GetCommandLine(); trace < L"::CreateProcessAsUser"; if (!CreateProcessAsUser( primaryNewUserSecurityTokenHandle, nullptr, commandLine.GetPointer(), &processSecAttributes, &threadSecAttributes, true, CREATE_UNICODE_ENVIRONMENT, newProcessEnvironmentResult.GetResultValue().CreateEnvironment(), workingDirectory.GetPointer(), &startupInfo, &processInformation)) { auto result = Error(L"CreateProcessAsUser"); UnloadUserProfile(primaryNewUserSecurityTokenHandle, profileInfo.hProfile); return result; } // ReSharper disable CppInitializedValueIsAlwaysRewritten // ReSharper disable CppEntityAssignedButNoRead auto processHandle = Handle(L"Service Process"); processHandle = processInformation.hProcess; auto threadHandle = Handle(L"Thread"); threadHandle = processInformation.hThread; auto exitCode = processTracker.WaiteForExit(processInformation.hProcess, trace); UnloadUserProfile(primaryNewUserSecurityTokenHandle, profileInfo.hProfile); return exitCode; }
static NTSTATUS HandleLogoff( IN OUT PWLSESSION Session, IN UINT Flags) { PLOGOFF_SHUTDOWN_DATA LSData; PSECURITY_ATTRIBUTES psa; HANDLE hThread; DWORD exitCode; NTSTATUS Status; /* Prepare data for logoff thread */ LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA)); if (!LSData) { ERR("Failed to allocate mem for thread data\n"); return STATUS_NO_MEMORY; } LSData->Flags = Flags; LSData->Session = Session; Status = CreateLogoffSecurityAttributes(&psa); if (!NT_SUCCESS(Status)) { ERR("Failed to create a required security descriptor. Status 0x%08lx\n", Status); HeapFree(GetProcessHeap(), 0, LSData); return Status; } /* Run logoff thread */ hThread = CreateThread(psa, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL); if (!hThread) { ERR("Unable to create logoff thread, error %lu\n", GetLastError()); DestroyLogoffSecurityAttributes(psa); HeapFree(GetProcessHeap(), 0, LSData); return STATUS_UNSUCCESSFUL; } WaitForSingleObject(hThread, INFINITE); if (!GetExitCodeThread(hThread, &exitCode)) { ERR("Unable to get exit code of logoff thread (error %lu)\n", GetLastError()); CloseHandle(hThread); DestroyLogoffSecurityAttributes(psa); HeapFree(GetProcessHeap(), 0, LSData); return STATUS_UNSUCCESSFUL; } CloseHandle(hThread); if (exitCode == 0) { ERR("Logoff thread returned failure\n"); DestroyLogoffSecurityAttributes(psa); HeapFree(GetProcessHeap(), 0, LSData); return STATUS_UNSUCCESSFUL; } SwitchDesktop(Session->WinlogonDesktop); // TODO: Play logoff sound! SetWindowStationUser(Session->InteractiveWindowStation, &LuidNone, NULL, 0); // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_LOGGINGOFF); // FIXME: Closing network connections! // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_CLOSINGNETWORKCONNECTIONS); /* Kill remaining COM apps. Only at logoff! */ hThread = CreateThread(psa, 0, KillComProcesses, (LPVOID)LSData, 0, NULL); if (hThread) { WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } /* We're done with the SECURITY_DESCRIPTOR */ DestroyLogoffSecurityAttributes(psa); psa = NULL; HeapFree(GetProcessHeap(), 0, LSData); DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_SAVEYOURSETTINGS); UnloadUserProfile(Session->UserToken, Session->hProfileInfo); CallNotificationDlls(Session, LogoffHandler); CloseHandle(Session->UserToken); UpdatePerUserSystemParameters(0, FALSE); Session->LogonState = STATE_LOGGED_OFF; Session->UserToken = NULL; return STATUS_SUCCESS; }
static BOOL HandleLogon( IN OUT PWLSESSION Session) { PROFILEINFOW ProfileInfo; BOOL ret = FALSE; /* Loading personal settings */ DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_LOADINGYOURPERSONALSETTINGS); ProfileInfo.hProfile = INVALID_HANDLE_VALUE; if (0 == (Session->Options & WLX_LOGON_OPT_NO_PROFILE)) { if (Session->Profile == NULL || (Session->Profile->dwType != WLX_PROFILE_TYPE_V1_0 && Session->Profile->dwType != WLX_PROFILE_TYPE_V2_0)) { ERR("WL: Wrong profile\n"); goto cleanup; } /* Load the user profile */ ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW)); ProfileInfo.dwSize = sizeof(PROFILEINFOW); ProfileInfo.dwFlags = 0; ProfileInfo.lpUserName = Session->MprNotifyInfo.pszUserName; ProfileInfo.lpProfilePath = Session->Profile->pszProfile; if (Session->Profile->dwType >= WLX_PROFILE_TYPE_V2_0) { ProfileInfo.lpDefaultPath = Session->Profile->pszNetworkDefaultUserProfile; ProfileInfo.lpServerName = Session->Profile->pszServerName; ProfileInfo.lpPolicyPath = Session->Profile->pszPolicy; } if (!LoadUserProfileW(Session->UserToken, &ProfileInfo)) { ERR("WL: LoadUserProfileW() failed\n"); goto cleanup; } } /* Create environment block for the user */ if (!CreateUserEnvironment(Session)) { WARN("WL: SetUserEnvironment() failed\n"); goto cleanup; } CallNotificationDlls(Session, LogonHandler); DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGYOURPERSONALSETTINGS); UpdatePerUserSystemParameters(0, TRUE); /* Set default user language */ if (!SetDefaultLanguage(Session)) { WARN("WL: SetDefaultLanguage() failed\n"); goto cleanup; } AllowWinstaAccess(Session); /* Connect remote resources */ RestoreAllConnections(Session); if (!StartUserShell(Session)) { //WCHAR StatusMsg[256]; WARN("WL: WlxActivateUserShell() failed\n"); //LoadStringW(hAppInstance, IDS_FAILEDACTIVATEUSERSHELL, StatusMsg, sizeof(StatusMsg) / sizeof(StatusMsg[0])); //MessageBoxW(0, StatusMsg, NULL, MB_ICONERROR); goto cleanup; } CallNotificationDlls(Session, StartShellHandler); if (!InitializeScreenSaver(Session)) WARN("WL: Failed to initialize screen saver\n"); Session->hProfileInfo = ProfileInfo.hProfile; /* Logon has succeeded. Play sound. */ PlayLogonSound(Session); ret = TRUE; cleanup: if (Session->Profile) { HeapFree(GetProcessHeap(), 0, Session->Profile->pszProfile); HeapFree(GetProcessHeap(), 0, Session->Profile); } Session->Profile = NULL; if (!ret && ProfileInfo.hProfile != INVALID_HANDLE_VALUE) { UnloadUserProfile(Session->UserToken, ProfileInfo.hProfile); } RemoveStatusMessage(Session); if (!ret) { SetWindowStationUser(Session->InteractiveWindowStation, &LuidNone, NULL, 0); CloseHandle(Session->UserToken); Session->UserToken = NULL; } if (ret) { SwitchDesktop(Session->ApplicationDesktop); Session->LogonState = STATE_LOGGED_ON; } return ret; }
bool StartProcess(Settings& settings, HANDLE hCmdPipe) { //Launching as one of: //1. System Account //2. Specified account (or limited account) //3. As current process DWORD gle = 0; BOOL bLoadedProfile = FALSE; PROFILEINFO profile = {0}; profile.dwSize = sizeof(profile); profile.lpUserName = (LPWSTR)(LPCWSTR)settings.user; profile.dwFlags = PI_NOUI; if(false == GetUserHandle(settings, bLoadedProfile, profile, hCmdPipe)) return false; PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {0}; si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; if(!BAD_HANDLE(settings.hStdErr)) { si.hStdError = settings.hStdErr; si.hStdInput = settings.hStdIn; si.hStdOutput = settings.hStdOut; si.dwFlags |= STARTF_USESTDHANDLES; #ifdef _DEBUG Log(L"DEBUG: Using redirected handles", false); #endif } #ifdef _DEBUG else Log(L"DEBUG: Not using redirected IO", false); #endif CString path = StrFormat(L"\"%s\"", settings.app); if(FALSE == settings.appArgs.IsEmpty()) { path += L" "; path += settings.appArgs; } LPCWSTR startingDir = NULL; if(FALSE == settings.workingDir.IsEmpty()) startingDir = settings.workingDir; DWORD launchGLE = 0; CleanupInteractive ci = {0}; if(settings.bInteractive || settings.bShowUIOnWinLogon) { BOOL b = PrepForInteractiveProcess(settings, &ci, settings.sessionToInteractWith); if(FALSE == b) Log(L"Failed to PrepForInteractiveProcess", true); if(NULL == si.lpDesktop) si.lpDesktop = L"WinSta0\\Default"; if(settings.bShowUIOnWinLogon) si.lpDesktop = L"winsta0\\Winlogon"; //Log(StrFormat(L"Using desktop: %s", si.lpDesktop), false); //http://blogs.msdn.com/b/winsdk/archive/2009/07/14/launching-an-interactive-process-from-windows-service-in-windows-vista-and-later.aspx //indicates desktop names are case sensitive } #ifdef _DEBUG Log(StrFormat(L"DEBUG: PAExec using desktop %s", si.lpDesktop == NULL ? L"{default}" : si.lpDesktop), false); #endif DWORD dwFlags = CREATE_SUSPENDED | CREATE_NEW_CONSOLE; LPVOID pEnvironment = NULL; VERIFY(CreateEnvironmentBlock(&pEnvironment, settings.hUser, TRUE)); if(NULL != pEnvironment) dwFlags |= CREATE_UNICODE_ENVIRONMENT; #ifdef _DEBUG gle = GetLastError(); Log(L"DEBUG: CreateEnvironmentBlock", gle); #endif if(settings.bDisableFileRedirection) DisableFileRedirection(); if(settings.bRunLimited) if(false == LimitRights(settings.hUser)) return false; if(settings.bRunElevated) if(false == ElevateUserToken(settings.hUser)) return false; CString user, domain; GetUserDomain(settings.user, user, domain); #ifdef _DEBUG Log(StrFormat(L"DEBUG: U:%s D:%s P:%s bP:%d Env:%s WD:%s", user, domain, settings.password, settings.bDontLoadProfile, pEnvironment ? L"true" : L"null", startingDir ? startingDir : L"null"), false); #endif BOOL bLaunched = FALSE; if(settings.bUseSystemAccount) { Log(StrFormat(L"PAExec starting process [%s] as Local System", path), false); if(BAD_HANDLE(settings.hUser)) Log(L"Have bad user handle", true); EnablePrivilege(SE_IMPERSONATE_NAME); BOOL bImpersonated = ImpersonateLoggedOnUser(settings.hUser); if(FALSE == bImpersonated) { Log(L"Failed to impersonate", GetLastError()); _ASSERT(bImpersonated); } EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME); EnablePrivilege(SE_INCREASE_QUOTA_NAME); bLaunched = CreateProcessAsUser(settings.hUser, NULL, path.LockBuffer(), NULL, NULL, TRUE, dwFlags, pEnvironment, startingDir, &si, &pi); launchGLE = GetLastError(); path.UnlockBuffer(); #ifdef _DEBUG if(0 != launchGLE) Log(StrFormat(L"Launch (launchGLE=%u) params: user=[x%X] path=[%s] flags=[x%X], pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]", launchGLE, (DWORD)settings.hUser, path, dwFlags, pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", (DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false); #endif RevertToSelf(); } else { if(FALSE == settings.user.IsEmpty()) //launching as a specific user { Log(StrFormat(L"PAExec starting process [%s] as %s", path, settings.user), false); if(false == settings.bRunLimited) { bLaunched = CreateProcessWithLogonW(user, domain.IsEmpty() ? NULL : domain, settings.password, settings.bDontLoadProfile ? 0 : LOGON_WITH_PROFILE, NULL, path.LockBuffer(), dwFlags, pEnvironment, startingDir, &si, &pi); launchGLE = GetLastError(); path.UnlockBuffer(); #ifdef _DEBUG if(0 != launchGLE) Log(StrFormat(L"Launch (launchGLE=%u) params: user=[%s] domain=[%s] prof=[x%X] path=[%s] flags=[x%X], pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]", launchGLE, user, domain, settings.bDontLoadProfile ? 0 : LOGON_WITH_PROFILE, path, dwFlags, pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", (DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false); #endif } else bLaunched = FALSE; //force to run with CreateProcessAsUser so rights can be limited //CreateProcessWithLogonW can't be called from LocalSystem on Win2003 and earlier, so LogonUser/CreateProcessAsUser must be used. Might as well try for everyone if((FALSE == bLaunched) && !BAD_HANDLE(settings.hUser)) { #ifdef _DEBUG Log(L"DEBUG: Failed CreateProcessWithLogonW - trying CreateProcessAsUser", GetLastError()); #endif EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME); EnablePrivilege(SE_INCREASE_QUOTA_NAME); EnablePrivilege(SE_IMPERSONATE_NAME); BOOL bImpersonated = ImpersonateLoggedOnUser(settings.hUser); if(FALSE == bImpersonated) { Log(L"Failed to impersonate", GetLastError()); _ASSERT(bImpersonated); } bLaunched = CreateProcessAsUser(settings.hUser, NULL, path.LockBuffer(), NULL, NULL, TRUE, CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, pEnvironment, startingDir, &si, &pi); if(0 == GetLastError()) launchGLE = 0; //mark as successful, otherwise return our original error path.UnlockBuffer(); #ifdef _DEBUG if(0 != launchGLE) Log(StrFormat(L"Launch (launchGLE=%u) params: user=[x%X] path=[%s] pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]", launchGLE, (DWORD)settings.hUser, path, pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", (DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false); #endif RevertToSelf(); } } else { Log(StrFormat(L"PAExec starting process [%s] as current user", path), false); EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME); EnablePrivilege(SE_INCREASE_QUOTA_NAME); EnablePrivilege(SE_IMPERSONATE_NAME); if(NULL != settings.hUser) bLaunched = CreateProcessAsUser(settings.hUser, NULL, path.LockBuffer(), NULL, NULL, TRUE, dwFlags, pEnvironment, startingDir, &si, &pi); if(FALSE == bLaunched) bLaunched = CreateProcess(NULL, path.LockBuffer(), NULL, NULL, TRUE, dwFlags, pEnvironment, startingDir, &si, &pi); launchGLE = GetLastError(); //#ifdef _DEBUG if(0 != launchGLE) Log(StrFormat(L"Launch (launchGLE=%u) params: path=[%s] user=[%s], pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]", launchGLE, path, settings.hUser ? L"{non-null}" : L"{null}", pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", (DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false); //#endif path.UnlockBuffer(); } } if(bLaunched) { if(gbInService) Log(L"Successfully launched", false); settings.hProcess = pi.hProcess; settings.processID = pi.dwProcessId; if(false == settings.allowedProcessors.empty()) { DWORD sysMask = 0, procMask = 0; VERIFY(GetProcessAffinityMask(pi.hProcess, &procMask, &sysMask)); procMask = 0; for(std::vector<WORD>::iterator itr = settings.allowedProcessors.begin(); settings.allowedProcessors.end() != itr; itr++) { DWORD bit = 1; bit = bit << (*itr - 1); procMask |= bit & sysMask; } VERIFY(SetProcessAffinityMask(pi.hProcess, procMask)); } VERIFY(SetPriorityClass(pi.hProcess, settings.priority)); ResumeThread(pi.hThread); VERIFY(CloseHandle(pi.hThread)); } else { Log(StrFormat(L"Failed to start %s.", path), launchGLE); if((ERROR_ELEVATION_REQUIRED == launchGLE) && (false == gbInService)) Log(L"HINT: PAExec probably needs to be \"Run As Administrator\"", false); } if(ci.bPreped) CleanUpInteractiveProcess(&ci); if(settings.bDisableFileRedirection) RevertFileRedirection(); if(NULL != pEnvironment) DestroyEnvironmentBlock(pEnvironment); pEnvironment = NULL; if(bLoadedProfile) UnloadUserProfile(settings.hUser, profile.hProfile); if(!BAD_HANDLE(settings.hUser)) { CloseHandle(settings.hUser); settings.hUser = NULL; } return bLaunched ? true : false; }
wchar_t *gethomedir_w(char *pUserName, char *pDomainName) { HANDLE token; PROFILEINFOW profileInfo; wchar_t szPathW[MAX_PATH] = {0}; wchar_t pUserName_w[UNLEN + 1] = {0}; static wchar_t username_w[UNLEN + 1] = {0}; DWORD usernamelen = UNLEN + 1; wchar_t pDomainName_w[UNLEN + 1] = {0}; wchar_t *userprofile_w; /* * If there is home dir from lsa return it. */ if (HomeDirLsaW[0] != L'\0') { debug("Using LSA HomeDirW."); return _wcsdup(HomeDirLsaW); } szPathW[0] = '\0'; if (MultiByteToWideChar(CP_UTF8, 0, pUserName, -1, pUserName_w, UNLEN) == 0) { return NULL; } if (pDomainName && MultiByteToWideChar(CP_UTF8, 0, pDomainName, -1, pDomainName_w, UNLEN) == 0) { return NULL; } debug3("gethomedir: pUserName [%s]", pUserName); GetUserNameW(username_w, &usernamelen); debug3("gethomedir: username [%ls]", username_w); if (wcscmp(pUserName_w, username_w) == 0) { /* * User query his own home dir, we can take it from env. */ debug3("gethomedir: getenv"); userprofile_w = _wgetenv(L"USERPROFILE"); if (userprofile_w) { debug3("gethomedir: userprofile [%ls]", userprofile_w); /* * We have a %USERPROFILE% and we can return it */ return _wcsdup(userprofile_w); } /* * Env not set, let's try to take it from token */ } /* * If all above fail try to create user token manually * and get homedir using this token. */ #ifdef USE_NTCREATETOKEN token = CreateUserTokenW(pUserName_w, pDomainName_w, L"sshd"); if (token == NULL) { debug("gethomedir: create token failed"); return NULL; } debug2("setting up profile info..."); /* * Become the user */ memset(&profileInfo, 0, sizeof(profileInfo)); profileInfo.dwSize = sizeof(profileInfo); profileInfo.lpUserName = pUserName_w; profileInfo.lpServerName = pDomainName_w; debug2("LoadUserProfile()..."); if (!LoadUserProfile(token, &profileInfo)) { DWORD dwLast = GetLastError(); debug("gethomedir: load profile failed [%d]", dwLast); return NULL; } /* * Get user's home directory */ //if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, token, 0, szPath))) debug2("SGGetFolderPath()..."); if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, token, 0, szPathW))) { debug("gethomedir: get folder failed"); /* * Become self again. */ UnloadUserProfile(token, profileInfo.hProfile); RevertToSelf(); CloseHandle(token); return NULL; } debug3("gethomedir: szPathW [%ls]", szPathW); /* * Become self again. */ UnloadUserProfile(token, profileInfo.hProfile); RevertToSelf(); CloseHandle(token); debug2("<- gethomedir()..."); return _wcsdup(szPathW); #else return NULL; #endif }
char *GetHomeDirFromToken(char *userName, HANDLE token) { UCHAR domain[200]; wchar_t pw_buf[MAX_PATH] = { L'\0' }; debug("-> GetHomeDirFromToken()..."); PROFILEINFO profileInfo; // find the server name of the domain controller which created this token GetDomainFromToken ( &token, domain, sizeof(domain)); //if (MultiByteToWideChar(CP_UTF8, 0, domain, -1, domainW, sizeof(domainW)) == 0) //{ //debug("DomainServerName encoding conversion failure"); //return NULL; //} profileInfo.dwFlags = PI_NOUI; profileInfo.lpProfilePath = NULL; profileInfo.lpUserName = userName; profileInfo.lpDefaultPath = NULL; profileInfo.lpServerName = domain; profileInfo.lpPolicyPath = NULL; profileInfo.hProfile = NULL; profileInfo.dwSize = sizeof(profileInfo); if (LoadUserProfile(token, &profileInfo) == FALSE) { debug("<- GetHomeDirFromToken()..."); debug("LoadUserProfile failure: %d", GetLastError()); return NULL; } /* * And retrieve homedir from profile. */ if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, token, 0, pw_homedir))) { debug("<- GetHomeDirFromToken()..."); debug("SHGetFolderPath failed"); return NULL; } // update APPDATA user's env variable if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, token, 0, pw_buf))) { SetEnvironmentVariableW(L"APPDATA", pw_buf); } // update LOCALAPPDATA user's env variable if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, token, 0, pw_buf))) { SetEnvironmentVariableW(L"LOCALAPPDATA", pw_buf); } /* * Unload user profile. */ if (UnloadUserProfile(token, profileInfo.hProfile) == FALSE) { debug("WARNING. Cannot unload user profile (%u).", GetLastError()); } debug("<- GetHomeDirFromToken()..."); return pw_homedir; }