blob: f33808533e9b664319baeb6c1eed7026fb86e41e [file] [log] [blame]
// Copyright 2017 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.
#import "ios/chrome/browser/passwords/credential_manager.h"
#include "base/mac/foundation_util.h"
#include "ios/chrome/browser/passwords/credential_manager_util.h"
#include "ios/chrome/browser/ssl/ios_security_state_tab_helper.h"
#include "ios/web/public/navigation_item.h"
#include "ios/web/public/navigation_manager.h"
#include "ios/web/public/ssl_status.h"
#include "ios/web/public/test/web_test_with_web_state.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace credential_manager {
namespace {
// Test hostname for cert verification.
constexpr char kHostName[] = "www.example.com";
// HTTPS origin corresponding to kHostName.
constexpr char kHttpsWebOrigin[] = "https://www.example.com/";
// HTTP origin corresponding to kHostName.
constexpr char kHttpWebOrigin[] = "http://www.example.com/";
// HTTP origin representing localhost. It should be considered secure.
constexpr char kLocalhostOrigin[] = "http://localhost";
// Origin with data scheme. It should be considered insecure.
constexpr char kDataUriSchemeOrigin[] = "data://www.example.com";
// File origin.
constexpr char kFileOrigin[] = "file://example_file";
// SSL certificate to load for testing.
constexpr char kCertFileName[] = "ok_cert.pem";
} // namespace
// TODO(crbug.com/435048): once JSCredentialManager is implemented and used
// from CredentialManager methods, mock it and write unit tests for
// CredentialManager methods SendGetResponse, SendStoreResponse and
// SendPreventSilentAccessResponse.
class CredentialManagerTest : public web::WebTestWithWebState {
public:
void SetUp() override {
WebTestWithWebState::SetUp();
// Used indirectly by WebStateContentIsSecureHtml function.
IOSSecurityStateTabHelper::CreateForWebState(web_state());
}
// Updates SSLStatus on web_state()->GetNavigationManager()->GetVisibleItem()
// with given |cert_status|, |security_style| and |content_status|.
// SSLStatus fields |certificate|, |connection_status| and |cert_status_host|
// are the same for all tests.
void UpdateSslStatus(net::CertStatus cert_status,
web::SecurityStyle security_style,
web::SSLStatus::ContentStatusFlags content_status) {
scoped_refptr<net::X509Certificate> cert =
net::ImportCertFromFile(net::GetTestCertsDirectory(), kCertFileName);
web::SSLStatus& ssl =
web_state()->GetNavigationManager()->GetVisibleItem()->GetSSL();
ssl.security_style = security_style;
ssl.certificate = cert;
ssl.cert_status = cert_status;
ssl.connection_status = net::SSL_CONNECTION_VERSION_SSL3;
ssl.content_status = content_status;
ssl.cert_status_host = kHostName;
}
};
class WebStateContentIsSecureHtmlTest : public CredentialManagerTest {};
// Tests that HTTPS websites with valid SSL certificate are recognized as
// secure.
TEST_F(WebStateContentIsSecureHtmlTest, AcceptHttpsUrls) {
LoadHtml(@"<html></html>", GURL(kHttpsWebOrigin));
UpdateSslStatus(net::CERT_STATUS_IS_EV, web::SECURITY_STYLE_AUTHENTICATED,
web::SSLStatus::NORMAL_CONTENT);
EXPECT_TRUE(WebStateContentIsSecureHtml(web_state()));
}
// Tests that WebStateContentIsSecureHtml returns false for HTTP origin.
TEST_F(WebStateContentIsSecureHtmlTest, HttpIsNotSecureContext) {
LoadHtml(@"<html></html>", GURL(kHttpWebOrigin));
EXPECT_FALSE(WebStateContentIsSecureHtml(web_state()));
}
// Tests that WebStateContentIsSecureHtml returns false for HTTPS origin with
// valid SSL certificate but mixed contents.
TEST_F(WebStateContentIsSecureHtmlTest, InsecureContent) {
LoadHtml(@"<html></html>", GURL(kHttpsWebOrigin));
UpdateSslStatus(net::CERT_STATUS_IS_EV, web::SECURITY_STYLE_AUTHENTICATED,
web::SSLStatus::DISPLAYED_INSECURE_CONTENT);
EXPECT_FALSE(WebStateContentIsSecureHtml(web_state()));
}
// Tests that WebStateContentIsSecureHtml returns false for HTTPS origin with
// invalid SSL certificate.
TEST_F(WebStateContentIsSecureHtmlTest, InvalidSslCertificate) {
LoadHtml(@"<html></html>", GURL(kHttpsWebOrigin));
UpdateSslStatus(net::CERT_STATUS_INVALID, web::SECURITY_STYLE_UNAUTHENTICATED,
web::SSLStatus::NORMAL_CONTENT);
EXPECT_FALSE(WebStateContentIsSecureHtml(web_state()));
}
// Tests that data:// URI scheme is not accepted as secure context.
TEST_F(WebStateContentIsSecureHtmlTest, DataUriSchemeIsNotSecureContext) {
LoadHtml(@"<html></html>", GURL(kDataUriSchemeOrigin));
EXPECT_FALSE(WebStateContentIsSecureHtml(web_state()));
}
// Tests that localhost is accepted as secure context.
TEST_F(WebStateContentIsSecureHtmlTest, LocalhostIsSecureContext) {
LoadHtml(@"<html></html>", GURL(kLocalhostOrigin));
EXPECT_TRUE(WebStateContentIsSecureHtml(web_state()));
}
// Tests that file origin is accepted as secure context.
TEST_F(WebStateContentIsSecureHtmlTest, FileIsSecureContext) {
LoadHtml(@"<html></html>", GURL(kFileOrigin));
EXPECT_TRUE(WebStateContentIsSecureHtml(web_state()));
}
// Tests that content must be HTML.
TEST_F(WebStateContentIsSecureHtmlTest, ContentMustBeHtml) {
// No HTML is loaded on purpose, so that web_state()->ContentIsHTML() will
// return false.
EXPECT_FALSE(WebStateContentIsSecureHtml(web_state()));
}
} // namespace credential_manager