| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_CREDENTIAL_PROVIDER_GAIACP_GCP_UTILS_H_ |
| #define CHROME_CREDENTIAL_PROVIDER_GAIACP_GCP_UTILS_H_ |
| |
| #include "base/callback.h" |
| #include "base/strings/string16.h" |
| #include "base/values.h" |
| #include "base/win/scoped_handle.h" |
| #include "base/win/windows_types.h" |
| #include "chrome/credential_provider/gaiacp/scoped_handle.h" |
| #include "chrome/credential_provider/gaiacp/scoped_lsa_policy.h" |
| #include "url/gurl.h" |
| |
| // These define are documented in |
| // https://msdn.microsoft.com/en-us/library/bb470234(v=vs.85).aspx not available |
| // in the user mode headers. |
| #define DIRECTORY_QUERY 0x00000001 |
| #define DIRECTORY_TRAVERSE 0x00000002 |
| #define DIRECTORY_CREATE_OBJECT 0x00000004 |
| #define DIRECTORY_CREATE_SUBDIRECTORY 0x00000008 |
| #define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) |
| |
| namespace base { |
| |
| class CommandLine; |
| class FilePath; |
| |
| } // namespace base |
| |
| namespace credential_provider { |
| |
| // Windows supports a maximum of 20 characters plus null in username. |
| constexpr int kWindowsUsernameBufferLength = 21; |
| |
| // Because of some strange dependency problems with windows header files, |
| // define STATUS_SUCCESS here instead of including ntstatus.h or SubAuth.h |
| #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) |
| |
| // The the UI process can exit with the following exit code. |
| enum UiExitCodes { |
| // The user completed the sign in successfully. |
| kUiecSuccess, |
| |
| // The sign in was aborted by the user. |
| kUiecAbort, |
| |
| // The sign in timed out. |
| kUiecTimeout, |
| |
| // The process was killed by the GCP. |
| kUiecKilled, |
| |
| // The email does not match the required pattern. |
| kUiecEMailMissmatch, |
| }; |
| |
| // A bitfield indicating which standard handles are to be created. |
| using StdHandlesToCreate = uint32_t; |
| |
| enum : uint32_t { |
| kStdOutput = 1 << 0, |
| kStdInput = 1 << 1, |
| kStdError = 1 << 2, |
| kAllStdHandles = kStdOutput | kStdInput | kStdError |
| }; |
| |
| // Filled in by InitializeStdHandles to return the parent side of stdin/stdout/ |
| // stderr pipes of the login UI process. |
| struct StdParentHandles { |
| StdParentHandles(); |
| ~StdParentHandles(); |
| |
| base::win::ScopedHandle hstdin_write; |
| base::win::ScopedHandle hstdout_read; |
| base::win::ScopedHandle hstderr_read; |
| }; |
| |
| // Process startup options that allows customization of stdin/stdout/stderr |
| // handles. |
| class ScopedStartupInfo { |
| public: |
| ScopedStartupInfo(); |
| explicit ScopedStartupInfo(const wchar_t* desktop); |
| ~ScopedStartupInfo(); |
| |
| // This function takes ownership of the handles. |
| HRESULT SetStdHandles(base::win::ScopedHandle* hstdin, |
| base::win::ScopedHandle* hstdout, |
| base::win::ScopedHandle* hstderr); |
| |
| LPSTARTUPINFOW GetInfo() { return &info_; } |
| |
| // Releases all resources held by this info. |
| void Shutdown(); |
| |
| private: |
| STARTUPINFOW info_; |
| base::string16 desktop_; |
| }; |
| |
| // Waits for the process specified by |procinfo| to terminate. The handles |
| // in |read_handles| can be used to read stdout/err from the process. Upon |
| // return, |exit_code| contains one of the UIEC_xxx constants listed above, |
| // and |stdout_buffer| and |stderr_buffer| contain the output, if any. |
| // Both buffers must be at least |buffer_size| characters long. |
| HRESULT WaitForProcess(base::win::ScopedHandle::Handle process_handle, |
| const StdParentHandles& parent_handles, |
| DWORD* exit_code, |
| char* output_buffer, |
| int buffer_size); |
| |
| // Creates a restricted, batch or interactive login token for the given user. |
| HRESULT CreateLogonToken(const wchar_t* username, |
| const wchar_t* password, |
| bool interactive, |
| base::win::ScopedHandle* token); |
| |
| HRESULT CreateJobForSignin(base::win::ScopedHandle* job); |
| |
| // Creates a pipe that can be used by a parent process to communicate with a |
| // child process. If |child_reads| is false, then it is expected that the |
| // parent process will read from |reading| anything the child process writes |
| // to |writing|. For example, this is used to read stdout/stderr of child. |
| // |
| // If |child_reads| is true, then it is expected that the child process will |
| // read from |reading| anything the parent process writes to |writing|. For |
| // example, this is used to write to stdin of child. |
| // |
| // If |use_nul| is true, then the parent's handle is not used (can be passed |
| // as nullptr). The child reads from or writes to the null device. |
| HRESULT CreatePipeForChildProcess(bool child_reads, |
| bool use_nul, |
| base::win::ScopedHandle* reading, |
| base::win::ScopedHandle* writing); |
| |
| // Initializes 3 pipes for communicating with a child process. On return, |
| // |startupinfo| will be set with the handles needed by the child. This is |
| // used when creating the child process. |parent_handles| contains the |
| // corresponding handles to be used by the parent process. |
| // |
| // Communication direction is used to optimize handle creation. If |
| // communication occurs in only one direction then some pipes will be directed |
| // to the nul device. |
| enum class CommDirection { |
| kParentToChildOnly, |
| kChildToParentOnly, |
| kBidirectional, |
| }; |
| HRESULT InitializeStdHandles(CommDirection direction, |
| StdHandlesToCreate to_create, |
| ScopedStartupInfo* startupinfo, |
| StdParentHandles* parent_handles); |
| |
| // Fills |path_to_dll| with the short path to the dll referenced by |
| // |dll_handle|. The short path is needed to correctly call rundll32.exe in |
| // cases where there might be quotes or spaces in the path. |
| HRESULT GetPathToDllFromHandle(HINSTANCE dll_handle, |
| base::FilePath* path_to_dll); |
| |
| // This function gets a correctly formatted entry point argument to pass to |
| // rundll32.exe for a dll referenced by the handle |dll_handle| and an entry |
| // point function with the name |entrypoint|. |entrypoint_arg| will be filled |
| // with the argument value. |
| HRESULT GetEntryPointArgumentForRunDll(HINSTANCE dll_handle, |
| const wchar_t* entrypoint, |
| base::string16* entrypoint_arg); |
| |
| // This function is used to build the command line for rundll32 to call an |
| // exported entrypoint from the DLL given by |dll_handle|. |
| // Returns S_FALSE if a command line can successfully be built but if the |
| // path to the "dll" actually points to a non ".dll" file. This allows |
| // detection of calls to this function via a unit test which will be |
| // running under an ".exe" module. |
| HRESULT GetCommandLineForEntrypoint(HINSTANCE dll_handle, |
| const wchar_t* entrypoint, |
| base::CommandLine* command_line); |
| |
| // Enrolls the machine to with the Google MDM server if not already. |
| HRESULT EnrollToGoogleMdmIfNeeded(const base::DictionaryValue& properties); |
| |
| // Gets the auth package id for NEGOSSP_NAME_A. |
| HRESULT GetAuthenticationPackageId(ULONG* id); |
| |
| // Gets a string resource from the DLL with the given id. |
| base::string16 GetStringResource(int base_message_id); |
| |
| // Gets the language selected by the base::win::i18n::LanguageSelector. |
| base::string16 GetSelectedLanguage(); |
| |
| // Helpers to get strings from DictionaryValues. |
| base::string16 GetDictString(const base::DictionaryValue* dict, |
| const char* name); |
| base::string16 GetDictString(const std::unique_ptr<base::DictionaryValue>& dict, |
| const char* name); |
| std::string GetDictStringUTF8(const base::DictionaryValue* dict, |
| const char* name); |
| std::string GetDictStringUTF8( |
| const std::unique_ptr<base::DictionaryValue>& dict, |
| const char* name); |
| |
| class OSUserManager; |
| class OSProcessManager; |
| |
| // This structure is used in tests to set fake objects in the credential |
| // provider dll. See the function SetFakesForTesting() for details. |
| struct FakesForTesting { |
| FakesForTesting(); |
| ~FakesForTesting(); |
| |
| ScopedLsaPolicy::CreatorCallback scoped_lsa_policy_creator; |
| OSUserManager* os_user_manager_for_testing = nullptr; |
| OSProcessManager* os_process_manager_for_testing = nullptr; |
| }; |
| |
| // DLL entrypoint signature for settings testing fakes. This is used by |
| // the setup tests to install fakes into the dynamically loaded gaia1_0 DLL |
| // static data. This way the production DLL does not need to include binary |
| // code used only for testing. |
| typedef void CALLBACK (*SetFakesForTestingFn)(const FakesForTesting* fakes); |
| |
| } // namespace credential_provider |
| |
| #endif // CHROME_CREDENTIAL_PROVIDER_GAIACP_GCP_UTILS_H_ |