Skip to content

Commit cec06e5

Browse files
cbiesingermibrunin
authored andcommitted
[Backport] Security bug 340895241 (1/2)
Partial manual cherry-pick of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/5564909: [FedCM] Download all profile pictures This ensures that we download the pictures even if the account later gets filtered out. This CL only does desktop because Android needs JNI changes for ImageDecoder first. We can't do the decoding in content/ because ImageDecoderImpl lives in chrome/. Bug: 340895241 Change-Id: Ie973c8ab57cc0810bb9b4d988904738e427421f2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5564909 Reviewed-by: Yi Gu <[email protected]> Reviewed-by: Dave Tapuska <[email protected]> Commit-Queue: Christian Biesinger <[email protected]> Cr-Commit-Position: refs/heads/main@{#1306939} Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/580289 Reviewed-by: Allan Sandfeld Jensen <[email protected]>
1 parent 668b779 commit cec06e5

File tree

5 files changed

+93
-3
lines changed

5 files changed

+93
-3
lines changed

chromium/content/browser/webid/federated_auth_request_impl.cc

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "content/browser/webid/federated_auth_request_impl.h"
66

7+
#include "base/barrier_closure.h"
78
#include "base/command_line.h"
89
#include "base/containers/contains.h"
910
#include "base/containers/cxx20_erase.h"
@@ -1102,7 +1103,7 @@ void FederatedAuthRequestImpl::OnClientMetadataResponseReceived(
11021103
IdpNetworkRequestManager::ClientMetadata client_metadata) {
11031104
// TODO(yigu): Clean up the client metadata related errors for metrics and
11041105
// console logs.
1105-
OnFetchDataForIdpSucceeded(std::move(idp_info), accounts, client_metadata);
1106+
FetchAccountPictures(std::move(idp_info), accounts, client_metadata);
11061107
}
11071108

11081109
bool HasScope(const std::vector<std::string>& scope, std::string name) {
@@ -1578,13 +1579,66 @@ void FederatedAuthRequestImpl::OnAccountsResponseReceived(
15781579
weak_ptr_factory_.GetWeakPtr(), std::move(idp_info),
15791580
std::move(accounts)));
15801581
} else {
1581-
OnFetchDataForIdpSucceeded(std::move(idp_info), accounts,
1582-
IdpNetworkRequestManager::ClientMetadata());
1582+
FetchAccountPictures(std::move(idp_info), accounts,
1583+
IdpNetworkRequestManager::ClientMetadata());
15831584
}
15841585
}
15851586
}
15861587
}
15871588

1589+
void FederatedAuthRequestImpl::FetchAccountPictures(
1590+
std::unique_ptr<IdentityProviderInfo> idp_info,
1591+
const IdpNetworkRequestManager::AccountList& accounts,
1592+
const IdpNetworkRequestManager::ClientMetadata& client_metadata) {
1593+
auto callback = BarrierClosure(
1594+
accounts.size(),
1595+
base::BindOnce(&FederatedAuthRequestImpl::OnAllAccountPicturesReceived,
1596+
weak_ptr_factory_.GetWeakPtr(), std::move(idp_info),
1597+
accounts, client_metadata));
1598+
for (const auto& account : accounts) {
1599+
if (account.picture.is_valid()) {
1600+
network_manager_->DownloadUncredentialedUrl(
1601+
account.picture,
1602+
base::BindOnce(&FederatedAuthRequestImpl::OnAccountPictureReceived,
1603+
weak_ptr_factory_.GetWeakPtr(), callback,
1604+
account.picture));
1605+
} else {
1606+
// We have to still call the callback to make sure the barrier
1607+
// callback gets the right number of calls.
1608+
callback.Run();
1609+
}
1610+
}
1611+
}
1612+
1613+
void FederatedAuthRequestImpl::OnAccountPictureReceived(
1614+
base::RepeatingClosure cb,
1615+
GURL url,
1616+
std::unique_ptr<std::string> response_body,
1617+
int response_code,
1618+
const std::string& mime_type) {
1619+
if (response_body) {
1620+
downloaded_images_[url] = std::move(response_body);
1621+
}
1622+
cb.Run();
1623+
}
1624+
1625+
void FederatedAuthRequestImpl::OnAllAccountPicturesReceived(
1626+
std::unique_ptr<IdentityProviderInfo> idp_info,
1627+
IdpNetworkRequestManager::AccountList accounts,
1628+
const IdpNetworkRequestManager::ClientMetadata& client_metadata) {
1629+
for (auto& account : accounts) {
1630+
auto it = downloaded_images_.find(account.picture);
1631+
if (it != downloaded_images_.end()) {
1632+
// We do not use std::move here in case multiple accounts use the
1633+
// same picture URL.
1634+
DCHECK(it->second);
1635+
account.picture_data = *it->second;
1636+
}
1637+
}
1638+
downloaded_images_.clear();
1639+
OnFetchDataForIdpSucceeded(std::move(idp_info), accounts, client_metadata);
1640+
}
1641+
15881642
void FederatedAuthRequestImpl::ComputeLoginStateAndReorderAccounts(
15891643
const IdentityProviderConfigPtr& idp,
15901644
IdpNetworkRequestManager::AccountList& accounts) {

chromium/content/browser/webid/federated_auth_request_impl.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,21 @@ class CONTENT_EXPORT FederatedAuthRequestImpl
239239
std::unique_ptr<IdentityProviderInfo> idp_info,
240240
IdpNetworkRequestManager::FetchStatus status,
241241
IdpNetworkRequestManager::AccountList accounts);
242+
// Fetches the account pictures for |accounts| and calls
243+
// OnFetchDataForIdpSucceeded when done.
244+
void FetchAccountPictures(
245+
std::unique_ptr<IdentityProviderInfo> idp_info,
246+
const IdpNetworkRequestManager::AccountList& accounts,
247+
const IdpNetworkRequestManager::ClientMetadata& client_metadata);
248+
void OnAccountPictureReceived(base::RepeatingClosure cb,
249+
GURL url,
250+
std::unique_ptr<std::string> response_body,
251+
int response_code,
252+
const std::string& mime_type);
253+
void OnAllAccountPicturesReceived(
254+
std::unique_ptr<IdentityProviderInfo> idp_info,
255+
IdpNetworkRequestManager::AccountList accounts,
256+
const IdpNetworkRequestManager::ClientMetadata& client_metadata);
242257
void OnAccountSelected(const GURL& idp_config_url,
243258
const std::string& account_id,
244259
bool is_sign_in);
@@ -357,6 +372,9 @@ class CONTENT_EXPORT FederatedAuthRequestImpl
357372
base::flat_map<GURL, std::unique_ptr<IdentityProviderInfo>> idp_infos_;
358373
std::vector<IdentityProviderData> idp_data_for_display_;
359374

375+
// The downloaded image data.
376+
std::map<GURL, std::unique_ptr<std::string>> downloaded_images_;
377+
360378
raw_ptr<FederatedIdentityApiPermissionContextDelegate>
361379
api_permission_delegate_ = nullptr;
362380
raw_ptr<FederatedIdentityAutoReauthnPermissionContextDelegate>

chromium/content/browser/webid/idp_network_request_manager.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,17 @@ void IdpNetworkRequestManager::SendLogout(const GURL& logout_url,
813813
maxResponseSizeInKiB * 1024);
814814
}
815815

816+
void IdpNetworkRequestManager::DownloadUncredentialedUrl(
817+
const GURL& url,
818+
DownloadCallback callback) {
819+
std::unique_ptr<network::ResourceRequest> resource_request =
820+
CreateUncredentialedResourceRequest(url, /*send_origin=*/false);
821+
822+
DownloadUrl(std::move(resource_request),
823+
/*url_encoded_post_data=*/std::nullopt, std::move(callback),
824+
maxResponseSizeInKiB * 1024);
825+
}
826+
816827
void IdpNetworkRequestManager::DownloadJsonAndParse(
817828
std::unique_ptr<network::ResourceRequest> resource_request,
818829
absl::optional<std::string> url_encoded_post_data,

chromium/content/browser/webid/idp_network_request_manager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ class CONTENT_EXPORT IdpNetworkRequestManager {
230230
// Send logout request to a single target.
231231
virtual void SendLogout(const GURL& logout_url, LogoutCallback);
232232

233+
// Download a URL. The request is made uncredentialed.
234+
virtual void DownloadUncredentialedUrl(const GURL& url,
235+
DownloadCallback callback);
236+
233237
private:
234238
// Starts download request using `url_loader`. Calls `parse_json_callback`
235239
// when the download result has been parsed.

chromium/content/public/browser/identity_request_account.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ struct CONTENT_EXPORT IdentityRequestAccount {
5757
std::string name;
5858
std::string given_name;
5959
GURL picture;
60+
// This will be an empty string if fetching failed.
61+
std::string picture_data;
62+
6063
std::vector<std::string> login_hints;
6164
std::vector<std::string> hosted_domains;
6265

0 commit comments

Comments
 (0)