Commit da48b024 authored by Yusuf Sengul's avatar Yusuf Sengul Committed by Commit Bot

Add common source files for gcpw extension

This change adds abstraction for the Windows APIs that
are used create and manage GCPW extension.

Bug: 1101590
Change-Id: I5fb88a6f73cc4c85f42728b9dee487d1067b8bc9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2278651
Commit-Queue: Yusuf Sengul <yusufsn@google.com>
Reviewed-by: default avatarRakesh Soma <rakeshsoma@google.com>
Cr-Commit-Position: refs/heads/master@{#791507}
parent 80b01933
......@@ -31,9 +31,22 @@ grit("extension_resources") {
]
}
source_set("common") {
sources = [
"extension_strings.cc",
"extension_strings.h",
"os_service_manager.cc",
"os_service_manager.h",
"scoped_handle.h",
]
deps = [ "//base:base" ]
configs += [ "//build/config/win:windowed" ]
}
executable("gcpw_extension") {
sources = [ "extension_main.cc" ]
deps = [
":common",
":extension_resources",
":version",
"../eventlog:gcp_eventlog_messages",
......
// Copyright 2020 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.
#include "chrome/credential_provider/extension/extension_strings.h"
namespace credential_provider {
namespace extension {
const wchar_t kGCPWExtensionServiceName[] = L"GCPWExtension";
const wchar_t kGCPWExtensionServiceDescription[] = L"GCPW extension service";
} // namespace extension
} // namespace credential_provider
// Copyright 2020 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_EXTENSION_EXTENSION_STRINGS_H_
#define CHROME_CREDENTIAL_PROVIDER_EXTENSION_EXTENSION_STRINGS_H_
namespace credential_provider {
namespace extension {
// Name of the GCPW extension service.
extern const wchar_t kGCPWExtensionServiceName[];
// Description of the GCPW extension service.
extern const wchar_t kGCPWExtensionServiceDescription[];
} // namespace extension
} // namespace credential_provider
#endif // CHROME_CREDENTIAL_PROVIDER_EXTENSION_EXTENSION_STRINGS_H_
// Copyright 2020 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.
#include "chrome/credential_provider/extension/os_service_manager.h"
#include "chrome/credential_provider/extension/extension_strings.h"
namespace credential_provider {
namespace extension {
OSServiceManager** OSServiceManager::GetInstanceStorage() {
static OSServiceManager* instance = new OSServiceManager();
return &instance;
}
// static
OSServiceManager* OSServiceManager::Get() {
return *GetInstanceStorage();
}
OSServiceManager::~OSServiceManager() {}
DWORD OSServiceManager::InstallService(
const base::FilePath& service_binary_path,
ScopedScHandle* sc_handle) {
ScopedScHandle scm_handle(
::OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT));
if (!scm_handle.IsValid())
return ::GetLastError();
*sc_handle = ScopedScHandle(::CreateService(
scm_handle.Get(), // SCM database
kGCPWExtensionServiceName, // name of service
kGCPWExtensionServiceDescription, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
service_binary_path.value().c_str(), // path to service's binary
nullptr, // no load ordering group
nullptr, // no tag identifier
nullptr, // no dependencies
nullptr, // LocalSystem account
nullptr));
if (!sc_handle->IsValid())
return ::GetLastError();
return ERROR_SUCCESS;
}
DWORD OSServiceManager::GetServiceStatus(SERVICE_STATUS* service_status) {
DCHECK(service_status);
ScopedScHandle scm_handle(
::OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT));
if (!scm_handle.IsValid())
return ::GetLastError();
ScopedScHandle sc_handle(::OpenService(
scm_handle.Get(), kGCPWExtensionServiceName, SERVICE_QUERY_STATUS));
if (!sc_handle.IsValid())
return ::GetLastError();
if (!::QueryServiceStatus(sc_handle.Get(), service_status)) {
return ::GetLastError();
}
return ERROR_SUCCESS;
}
DWORD OSServiceManager::DeleteService() {
ScopedScHandle scm_handle(
::OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS));
if (!scm_handle.IsValid())
return ::GetLastError();
ScopedScHandle sc_handle(
::OpenService(scm_handle.Get(), kGCPWExtensionServiceName, DELETE));
if (!sc_handle.IsValid())
return ::GetLastError();
// The DeleteService function marks a service for deletion from the service
// control manager database. The database entry is not removed until all open
// handles to the service have been closed by calls to the CloseServiceHandle
// function, and the service is not running.
if (!::DeleteService(sc_handle.Get()))
return ::GetLastError();
return ERROR_SUCCESS;
}
DWORD OSServiceManager::ControlService(DWORD control,
SERVICE_STATUS* service_status) {
DCHECK(service_status);
ScopedScHandle scm_handle(
::OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS));
if (!scm_handle.IsValid())
return ::GetLastError();
// TODO(crbug.com/1108932): More granular access rights corresponding to the
// controls can be specified.
ScopedScHandle s_handle(::OpenService(
scm_handle.Get(), kGCPWExtensionServiceName, SERVICE_ALL_ACCESS));
if (!s_handle.IsValid())
return ::GetLastError();
if (!::ControlService(s_handle.Get(), control,
(LPSERVICE_STATUS)&service_status))
return ::GetLastError();
return ERROR_SUCCESS;
}
DWORD OSServiceManager::StartServiceCtrlDispatcher(
LPSERVICE_MAIN_FUNCTION service_main) {
SERVICE_TABLE_ENTRY dispatch_table[] = {
{(LPWSTR)kGCPWExtensionServiceName, service_main}, {nullptr, nullptr}};
if (!::StartServiceCtrlDispatcher(dispatch_table))
return ::GetLastError();
return ERROR_SUCCESS;
}
DWORD OSServiceManager::RegisterCtrlHandler(
LPHANDLER_FUNCTION handler_proc,
SERVICE_STATUS_HANDLE* service_status_handle) {
DCHECK(handler_proc);
DCHECK(service_status_handle);
SERVICE_STATUS_HANDLE sc_status_handle =
::RegisterServiceCtrlHandler(kGCPWExtensionServiceName, handler_proc);
if (!sc_status_handle)
return ::GetLastError();
*service_status_handle = sc_status_handle;
return ERROR_SUCCESS;
}
DWORD OSServiceManager::SetServiceStatus(
SERVICE_STATUS_HANDLE service_status_handle,
SERVICE_STATUS service) {
if (!::SetServiceStatus(service_status_handle, &service))
return ::GetLastError();
return ERROR_SUCCESS;
}
} // namespace extension
} // namespace credential_provider
// Copyright 2020 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_EXTENSION_OS_SERVICE_MANAGER_H_
#define CHROME_CREDENTIAL_PROVIDER_EXTENSION_OS_SERVICE_MANAGER_H_
#include <windows.h>
#include "base/files/file_path.h"
#include "chrome/credential_provider/extension/scoped_handle.h"
namespace credential_provider {
namespace extension {
class OSServiceManager {
public:
static OSServiceManager* Get();
virtual ~OSServiceManager();
// Creates a service object and adds it to the specified service control
// manager database. Uses the |service_binary_path| as the location of service
// binary. Returns handle of the service in |sc_handle| parameter.
DWORD InstallService(const base::FilePath& service_binary_path,
ScopedScHandle* sc_handle);
// Uses The QueryServiceStatus API which returns the most recent service
// status information reported to the service control manager. The
// |service_status| receives the latest status of the service. SERVICE_STATUS
// is obtained via QueryServiceStatus API call.
DWORD GetServiceStatus(SERVICE_STATUS* service_status);
// The DeleteService function marks a service for deletion from the service
// control manager database. The database entry is not removed until all open
// handles to the service have been closed by calls to the CloseServiceHandle
// function, and the service is not running.
DWORD DeleteService();
// Calls the ControlService API to change the state of the service. |control|
// needs to be one of the service controls as specified in documentation [1].
// As a result |service_status| is returned that has the latest state of the
// service. [1]
// https://docs.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-controlservice
DWORD ControlService(DWORD control, SERVICE_STATUS* service_status);
// When the service control manager starts a service process, it waits for the
// process to call the StartServiceCtrlDispatcher function. The main thread of
// a service process should make this call as soon as possible after it starts
// up (within 30 seconds). If StartServiceCtrlDispatcher succeeds, it connects
// the calling thread to the service control manager and does not return until
// all running services in the process have entered the SERVICE_STOPPED state.
// The lpServiceTable parameter contains an entry for each service that can
// run in the calling process. Each entry specifies the ServiceMain function
// for that service.
DWORD StartServiceCtrlDispatcher(LPSERVICE_MAIN_FUNCTION service_main);
// Registers a function to handle service control requests.
DWORD RegisterCtrlHandler(LPHANDLER_FUNCTION handler_proc,
SERVICE_STATUS_HANDLE* service_status_handle);
// Updates the service control manager's status information for the calling
// service.
DWORD SetServiceStatus(SERVICE_STATUS_HANDLE service_status_handle,
SERVICE_STATUS service);
protected:
OSServiceManager() {}
// Returns the storage used for the instance pointer.
static OSServiceManager** GetInstanceStorage();
};
} // namespace extension
} // namespace credential_provider
#endif // CHROME_CREDENTIAL_PROVIDER_EXTENSION_OS_SERVICE_MANAGER_H_
// Copyright 2020 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_EXTENSION_SCOPED_HANDLE_H_
#define CHROME_CREDENTIAL_PROVIDER_EXTENSION_SCOPED_HANDLE_H_
#include <windows.h>
#include "base/macros.h"
#include "base/win/scoped_handle.h"
namespace credential_provider {
namespace extension {
class ScHandleTraits {
public:
typedef SC_HANDLE Handle;
static bool CloseHandle(SC_HANDLE handle) {
return ::CloseServiceHandle(handle) != FALSE;
}
static bool IsHandleValid(SC_HANDLE handle) { return handle != nullptr; }
static SC_HANDLE NullHandle() { return nullptr; }
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ScHandleTraits);
};
typedef base::win::GenericScopedHandle<ScHandleTraits,
base::win::DummyVerifierTraits>
ScopedScHandle;
class TimerTraits {
public:
using Handle = HANDLE;
static bool CloseHandle(HANDLE handle) {
return ::DeleteTimerQueue(handle) != FALSE;
}
static bool IsHandleValid(HANDLE handle) { return handle != nullptr; }
static HANDLE NullHandle() { return nullptr; }
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(TimerTraits);
};
typedef base::win::GenericScopedHandle<TimerTraits,
base::win::DummyVerifierTraits>
ScopedTimerHandle;
} // namespace extension
} // namespace credential_provider
#endif // CHROME_CREDENTIAL_PROVIDER_EXTENSION_SCOPED_HANDLE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment