1
// vim:expandtab:shiftwidth=2:tabstop=2:
2
// Copyright (C) 2014 Canonical Ltd.
4
// This library is free software; you can redistribute it and/or
5
// modify it under the terms of the GNU Lesser General Public
6
// License as published by the Free Software Foundation; either
7
// version 2.1 of the License, or (at your option) any later version.
9
// This library is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
// Lesser General Public License for more details.
14
// You should have received a copy of the GNU Lesser General Public
15
// License along with this library; if not, write to the Free Software
16
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
#include "oxide_security_status.h"
20
#include "base/logging.h"
21
#include "content/public/browser/cert_store.h"
22
#include "content/public/common/security_style.h"
23
#include "net/cert/cert_status_flags.h"
24
#include "net/cert/x509_certificate.h"
26
#include "shared/base/oxide_enum_flags.h"
32
OXIDE_MAKE_ENUM_BITWISE_OPERATORS(content::SSLStatus::ContentStatusFlags)
33
OXIDE_MAKE_ENUM_BITWISE_OPERATORS(CertStatus)
35
inline SecurityLevel CalculateSecurityLevel(
36
const content::SSLStatus& ssl_status,
37
net::X509Certificate* cert) {
38
if (ssl_status.security_style == content::SECURITY_STYLE_UNKNOWN ||
39
ssl_status.security_style == content::SECURITY_STYLE_UNAUTHENTICATED) {
40
return SECURITY_LEVEL_NONE;
43
if (ssl_status.security_style ==
44
content::SECURITY_STYLE_AUTHENTICATION_BROKEN) {
45
return SECURITY_LEVEL_ERROR;
48
DCHECK_EQ(ssl_status.security_style, content::SECURITY_STYLE_AUTHENTICATED);
49
CHECK(!(ssl_status.content_status &
50
content::SSLStatus::RAN_INSECURE_CONTENT)) <<
51
"Invalid SSLStatus - RAN_INSECURE_CONTENT and SECURITY_STYLE_AUTHENTICATED "
52
"are meant to be mutually exclusive!";
54
if (ssl_status.content_status &
55
content::SSLStatus::DISPLAYED_INSECURE_CONTENT) {
56
return SECURITY_LEVEL_WARNING;
60
static_cast<content::SSLStatus::ContentStatusFlags>(
61
ssl_status.content_status),
62
content::SSLStatus::NORMAL_CONTENT);
64
if (net::IsCertStatusError(ssl_status.cert_status)) {
65
CHECK(net::IsCertStatusMinorError(ssl_status.cert_status)) <<
66
"Invalid SSLStatus - Non-minor cert status error and "
67
"SECURITY_STYLE_AUTHENTICATED are meant to be mutually exclusive!";
68
return SECURITY_LEVEL_WARNING;
71
if ((ssl_status.cert_status & net::CERT_STATUS_IS_EV) && cert) {
72
return SECURITY_LEVEL_SECURE_EV;
75
return SECURITY_LEVEL_SECURE;
78
inline CertStatus CalculateCertStatus(net::CertStatus cert_status,
79
net::X509Certificate* cert) {
80
CertStatus rv = CERT_STATUS_OK;
82
// Handle flags that have a direct mapping to CertErrorStatus first
83
if (cert_status & net::CERT_STATUS_COMMON_NAME_INVALID) {
84
rv |= CERT_STATUS_BAD_IDENTITY;
85
cert_status &= ~net::CERT_STATUS_COMMON_NAME_INVALID;
87
if (cert_status & net::CERT_STATUS_DATE_INVALID) {
88
if (cert && cert->HasExpired()) {
89
rv |= CERT_STATUS_EXPIRED;
91
// The date could be in the future or issuer certificates could
92
// have expired. In the latter case, perhaps make this
93
// CERT_STATUS_EXPIRED too?
94
rv |= CERT_STATUS_DATE_INVALID;
96
cert_status &= ~net::CERT_STATUS_DATE_INVALID;
98
if (cert_status & net::CERT_STATUS_AUTHORITY_INVALID) {
99
rv |= CERT_STATUS_AUTHORITY_INVALID;
100
cert_status &= ~net::CERT_STATUS_AUTHORITY_INVALID;
102
if (cert_status & net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION) {
103
rv |= CERT_STATUS_REVOCATION_CHECK_FAILED;
104
cert_status &= ~net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
106
if (cert_status & net::CERT_STATUS_REVOKED) {
107
rv |= CERT_STATUS_REVOKED;
108
cert_status &= ~net::CERT_STATUS_REVOKED;
110
if (cert_status & net::CERT_STATUS_INVALID) {
111
rv |= CERT_STATUS_INVALID;
112
cert_status &= ~net::CERT_STATUS_INVALID;
114
if (cert_status & net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM) {
115
rv |= CERT_STATUS_INSECURE;
116
cert_status &= ~net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
118
if (cert_status & net::CERT_STATUS_WEAK_KEY) {
119
rv |= CERT_STATUS_INSECURE;
120
cert_status &= ~net::CERT_STATUS_WEAK_KEY;
123
// For flags that don't have a direct mapping to CertErrorStatus,
124
// set the generic flag if any non-minor error bits are set
125
if (net::IsCertStatusError(cert_status) &&
126
!net::IsCertStatusMinorError(cert_status)) {
127
rv |= CERT_STATUS_GENERIC_ERROR;
135
SecurityStatus::SecurityStatus()
136
: security_level_(SECURITY_LEVEL_NONE),
137
content_status_(content::SSLStatus::NORMAL_CONTENT),
138
cert_status_(CERT_STATUS_OK) {}
140
SecurityStatus::SecurityStatus(const content::SSLStatus& ssl_status)
141
: security_level_(SECURITY_LEVEL_NONE),
142
content_status_(content::SSLStatus::NORMAL_CONTENT),
143
cert_status_(CERT_STATUS_OK) {
147
SecurityStatus::~SecurityStatus() {}
149
void SecurityStatus::Update(const content::SSLStatus& ssl_status) {
151
content::CertStore::GetInstance()->RetrieveCert(ssl_status.cert_id,
154
security_level_ = CalculateSecurityLevel(ssl_status, cert_.get());
155
content_status_ = static_cast<content::SSLStatus::ContentStatusFlags>(
156
ssl_status.content_status);
157
cert_status_ = CalculateCertStatus(ssl_status.cert_status, cert_.get());
160
scoped_refptr<net::X509Certificate> SecurityStatus::cert() const {