Example #1
0
/* 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;
	}
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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
}
Example #8
0
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;
}