chromium/chrome/credential_provider/gaiacp/gaia_credential_provider_filter.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chrome/credential_provider/gaiacp/gaia_credential_provider_filter.h"

#include <string>

#include "build/branding_buildflags.h"
#include "chrome/credential_provider/gaiacp/associated_user_validator.h"
#include "chrome/credential_provider/gaiacp/auth_utils.h"
#include "chrome/credential_provider/gaiacp/chrome_availability_checker.h"
#include "chrome/credential_provider/gaiacp/gcp_utils.h"
#include "chrome/credential_provider/gaiacp/logging.h"

namespace credential_provider {

#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const CLSID CLSID_CGaiaCredentialProviderFilter = {
    0xaec62ffe,
    0x6617,
    0x4685,
    {0xa0, 0x80, 0xb1, 0x1a, 0x84, 0x8a, 0x06, 0x07}};
#else
const CLSID CLSID_CGaiaCredentialProviderFilter = {
    0xfd768777,
    0x340e,
    0x4426,
    {0x9b, 0x07, 0x8f, 0xdf, 0x48, 0x9f, 0x1f, 0xf9}};
#endif

CGaiaCredentialProviderFilter::CGaiaCredentialProviderFilter() = default;

CGaiaCredentialProviderFilter::~CGaiaCredentialProviderFilter() = default;

HRESULT CGaiaCredentialProviderFilter::FinalConstruct() {
  LOGFN(VERBOSE);
  return S_OK;
}

void CGaiaCredentialProviderFilter::FinalRelease() {
  LOGFN(VERBOSE);
}

HRESULT CGaiaCredentialProviderFilter::Filter(
    CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
    DWORD flags,
    GUID* providers_clsids,
    BOOL* providers_allow,
    DWORD providers_count) {
  // Re-enable all users in case internet has been lost or the computer
  // crashed while users were locked out.
  AssociatedUserValidator::Get()->AllowSigninForAllAssociatedUsers(cpus);

  // If a supported version of Chrome is not found, return right away so that
  // we don't revoke any access to normal credential providers.
  if (!ChromeAvailabilityChecker::Get()->HasSupportedChromeVersion()) {
    // Filter out the GaiaCredentialProvider in this case.
    for (DWORD i = 0; i < providers_count; ++i) {
      if (providers_clsids[i] == CLSID_GaiaCredentialProvider)
        providers_allow[i] = FALSE;
    }

    // Delete the startup sentinel file since if Chrome is not installed/usable
    // we will repeatedly fail and will hit the maximum number of crashes
    // after which we stop associating as a credential provider.
    DeleteStartupSentinel();
    LOGFN(ERROR) << "Supported Chrome version not found.";
    return S_OK;
  }

  // Update sid mapping at least once before invoking any other  methods in the
  // later stages.
  AssociatedUserValidator::Get()->UpdateAssociatedSids(nullptr);

  return S_OK;
}

HRESULT CGaiaCredentialProviderFilter::UpdateRemoteCredential(
    const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs_in,
    CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs_out) {
  // Don't do anything if Chrome is not found.
  if (!ChromeAvailabilityChecker::Get()->HasSupportedChromeVersion())
    return E_NOTIMPL;

  if (!pcpcs_out)
    return E_NOTIMPL;

  ULONG auth_package_id;
  HRESULT hr = GetAuthenticationPackageId(&auth_package_id);
  if (FAILED(hr))
    return E_NOTIMPL;

  if (pcpcs_in->ulAuthenticationPackage != auth_package_id)
    return E_NOTIMPL;

  if (pcpcs_in->cbSerialization == 0)
    return E_NOTIMPL;

  // If serialziation data is set, try to extract the sid for the user
  // referenced in the serialization data.
  std::wstring serialization_sid;
  hr = DetermineUserSidFromAuthenticationBuffer(pcpcs_in, &serialization_sid);
  if (FAILED(hr))
    return E_NOTIMPL;

  // Check if this user needs a reauth, if not, just pass the serialization
  // to the default handler.
  if (!AssociatedUserValidator::Get()->IsAuthEnforcedForUser(
          serialization_sid)) {
    return E_NOTIMPL;
  }

  // Copy out the serialization data to pass it into the provider.
  byte* serialization_buffer =
      (BYTE*)::CoTaskMemAlloc(pcpcs_in->cbSerialization);
  if (serialization_buffer == nullptr)
    return E_NOTIMPL;

  pcpcs_out->rgbSerialization = serialization_buffer;
  memcpy(pcpcs_out->rgbSerialization, pcpcs_in->rgbSerialization,
         pcpcs_in->cbSerialization);
  pcpcs_out->cbSerialization = pcpcs_in->cbSerialization;
  pcpcs_out->clsidCredentialProvider = CLSID_GaiaCredentialProvider;
  pcpcs_out->ulAuthenticationPackage = pcpcs_in->ulAuthenticationPackage;

  return S_OK;
}

}  // namespace credential_provider