static BOOL AllowWinstaAccess(PWLSESSION Session) { BOOL bSuccess = FALSE; DWORD dwIndex; DWORD dwLength = 0; PTOKEN_GROUPS ptg = NULL; PSID psid; TOKEN_STATISTICS Stats; DWORD cbStats; DWORD ret; // Get required buffer size and allocate the TOKEN_GROUPS buffer. if (!GetTokenInformation(Session->UserToken, TokenGroups, ptg, 0, &dwLength)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (ptg == NULL) return FALSE; } // Get the token group information from the access token. if (!GetTokenInformation(Session->UserToken, TokenGroups, ptg, dwLength, &dwLength)) { goto Cleanup; } // Loop through the groups to find the logon SID. for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) { if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID) { psid = ptg->Groups[dwIndex].Sid; break; } } dwLength = GetLengthSid(psid); if (!GetTokenInformation(Session->UserToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &cbStats)) { WARN("Couldn't get Authentication id from user token!\n"); goto Cleanup; } AddAceToWindowStation(Session->InteractiveWindowStation, psid); ret = SetWindowStationUser(Session->InteractiveWindowStation, &Stats.AuthenticationId, psid, dwLength); TRACE("SetWindowStationUser returned 0x%x\n", ret); bSuccess = TRUE; Cleanup: // Free the buffer for the token groups. if (ptg != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)ptg); return bSuccess; }
ActivePet::ActivePet(wchar_t* user_password, std::wstring petname, FileEventLoop* files) : m_petname(petname), m_files(files), m_session(INVALID_HANDLE_VALUE), m_profile(INVALID_HANDLE_VALUE), m_job(CreateJobObject(NULL, NULL)), m_next_editable_name(1), m_ticks_while_invisible(0) { // Create a new logon session for the pet. std::wstring petRegistryPath = Constants::registryPets() + L"\\" + m_petname; RegKey petkey = RegKey::HKCU.open(petRegistryPath); std::wstring accountName = petkey.getValue(L"accountName"); std::wstring accountRegistryPath = Constants::registryAccounts() + L"\\" + accountName; RegKey accountKey = RegKey::HKCU.open(accountRegistryPath); std::wstring password = accountKey.getValue(L"password"); if (!LogonUser(accountName.c_str(), NULL, password.c_str(), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &m_session)) { printf("LogonUser() failed: %d\n", GetLastError()); return; } // Tweak the Winsta0 and desktop ACLs to allow the pet to create windows. 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\n", GetLastError()); return; } if (!AddAceToWindowStation(winsta0.get(), logon_sid.get())) { printf("AddAceToWindowStation() 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\n", GetLastError()); return; } if (!AddAceToDesktop(desktop.get(), logon_sid.get())) { printf("AddAceToDesktop() failed: %d\n", GetLastError()); return; } // Load the pet account's registry hive. wchar_t account[128] = {}; wcsncpy(account, accountName.c_str(), 128); PROFILEINFO profile = { sizeof(PROFILEINFO), 0, account }; if (!LoadUserProfile(m_session.get(), &profile)) { printf("LoadUserProfile() failed: %d\n", GetLastError()); return; } m_profile = profile.hProfile; // Initialize the pet job. if (NULL == m_job.get()) { printf("CreateJobObject() failed: %d\n", GetLastError()); return; } JOBOBJECT_BASIC_UI_RESTRICTIONS buir = { JOB_OBJECT_UILIMIT_HANDLES }; if (!SetInformationJobObject(m_job.get(), JobObjectBasicUIRestrictions, &buir, sizeof buir)) { printf("SetInformationJobObject() failed: %d\n", GetLastError()); } // Some apps fail to launch without access to the desktop window. if (!UserHandleGrantAccess(GetDesktopWindow(), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } // Give apps access to all the standard cursors. if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_ARROW), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_IBEAM), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_WAIT), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_CROSS), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_UPARROW), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZE), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_ICON), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZENWSE), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZENESW), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZEWE), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZENS), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZEALL), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_NO), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_HAND), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_APPSTARTING), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_HELP), m_job.get(), TRUE)) { printf("UserHandleGrantAccess() failed: %d\n", GetLastError()); } // Setup the use records for the printers. std::set<std::wstring> servers; RegKey printers = RegKey::HKCU.open(L"Printers\\Connections"); for (int i = 0; true; ++i) { RegKey printer = printers.getSubKey(i); if (!printer.isGood()) { break; } std::wstring server = printer.getValue(L"Server"); if (servers.count(server) == 0) { std::wstring resource = server + L"\\IPC$"; auto_array<wchar_t> remote(resource.length() + 1); lstrcpy(remote.get(), resource.c_str()); USE_INFO_2 use = {}; use.ui2_remote = remote.get(); use.ui2_domainname = _wgetenv(L"USERDOMAIN"); use.ui2_username = _wgetenv(L"USERNAME");; use.ui2_password = user_password; use.ui2_asg_type = USE_WILDCARD; auto_impersonation impersonate(m_session.get()); DWORD arg_error; NET_API_STATUS error = NetUseAdd(NULL, 2, (BYTE*)&use, &arg_error); if (error) { printf("NetUseAdd() failed: %d\n", error); } else { servers.insert(server); } } } // Add the message handlers. //m_requestFolderPath = accountKey.getValue(Constants::petDataPathName()) + Constants::requestPath(); m_requestFolderPath = Constants::requestsPath(Constants::polarisDataPath(Constants::userProfilePath(accountName))); m_dispatcher = new MessageDispatcher(m_requestFolderPath); m_files->watch(m_requestFolderPath, m_dispatcher); m_dispatcher->add("sendmail",makeSendMailHandler()); // TODO m_dispatcher->add("GetOpenFileNameA", makeGetOpenFileNameAHandler(this)); m_dispatcher->add("GetOpenFileNameW", makeGetOpenFileNameWHandler(this)); m_dispatcher->add("GetClipboardData", makeGetClipboardDataHandler()); }
BOOL StartInteractiveClientProcess ( LPTSTR lpszUsername, // client to log on LPTSTR lpszDomain, // domain of client's account LPTSTR lpszPassword, // client's password LPTSTR lpCommandLine // command line to execute ) { HANDLE hToken; HDESK hdesk = NULL; HWINSTA hwinsta = NULL, hwinstaSave = NULL; PROCESS_INFORMATION pi; PSID pSid = NULL; STARTUPINFO si; BOOL bResult = FALSE; // Log the client on to the local computer. if (!LogonUser( lpszUsername, lpszDomain, lpszPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken) ) { goto Cleanup; } // Save a handle to the caller's current window station. if ( (hwinstaSave = GetProcessWindowStation() ) == NULL) goto Cleanup; // Get a handle to the interactive window station. hwinsta = OpenWindowStation( _T("winsta0"), // the interactive window station FALSE, // handle is not inheritable READ_CONTROL | WRITE_DAC); // rights to read/write the DACL if (hwinsta == NULL) goto Cleanup; // To get the correct default desktop, set the caller's // window station to the interactive window station. if (!SetProcessWindowStation(hwinsta)) goto Cleanup; // Get a handle to the interactive desktop. hdesk = OpenDesktop( _T("default"), // the interactive window station 0, // no interaction with other desktop processes FALSE, // handle is not inheritable READ_CONTROL | // request the rights to read and write the DACL WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS); // Restore the caller's window station. if (!SetProcessWindowStation(hwinstaSave)) goto Cleanup; if (hdesk == NULL) goto Cleanup; // Get the SID for the client's logon session. if (!GetLogonSID(hToken, &pSid)) goto Cleanup; // Allow logon SID full access to interactive window station. if (! AddAceToWindowStation(hwinsta, pSid) ) goto Cleanup; // Allow logon SID full access to interactive desktop. if (! AddAceToDesktop(hdesk, pSid) ) goto Cleanup; // Impersonate client to ensure access to executable file. if (! ImpersonateLoggedOnUser(hToken) ) goto Cleanup; // Initialize the STARTUPINFO structure. // Specify that the process runs in the interactive desktop. ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb= sizeof(STARTUPINFO); si.lpDesktop = TEXT("winsta0\\default"); // Launch the process in the client's logon session. bResult = CreateProcessAsUser( hToken, // client's access token NULL, // file to execute lpCommandLine, // command line NULL, // pointer to process SECURITY_ATTRIBUTES NULL, // pointer to thread SECURITY_ATTRIBUTES FALSE, // handles are not inheritable NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, // creation flags NULL, // pointer to new environment block NULL, // name of current directory &si, // pointer to STARTUPINFO structure &pi // receives information about new process ); // End impersonation of client. RevertToSelf(); if (bResult && pi.hProcess != INVALID_HANDLE_VALUE) { WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); } if (pi.hThread != INVALID_HANDLE_VALUE) CloseHandle(pi.hThread); Cleanup: if (hwinstaSave != NULL) SetProcessWindowStation (hwinstaSave); // Free the buffer for the logon SID. if (pSid) FreeLogonSID(&pSid); // Close the handles to the interactive window station and desktop. if (hwinsta) CloseWindowStation(hwinsta); if (hdesk) CloseDesktop(hdesk); // Close the handle to the client's access token. if (hToken != INVALID_HANDLE_VALUE) CloseHandle(hToken); return bResult; }