summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ssl/ssl_error_classification.h
blob: cb07f8f9cb342b8fdd793dfe9217d6af027d434f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2014 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_BROWSER_SSL_SSL_ERROR_CLASSIFICATION_H_
#define CHROME_BROWSER_SSL_SSL_ERROR_CLASSIFICATION_H_

#include <string>
#include <vector>

#include "base/time/time.h"
#include "net/cert/x509_certificate.h"
#include "url/gurl.h"

// This class calculates the severity scores for the different type of SSL
// errors.
class SSLErrorClassification {
 public:
  SSLErrorClassification(const base::Time& current_time,
                         const GURL& url,
                         const net::X509Certificate& cert);
  ~SSLErrorClassification();

  // Returns true if the system time is in the past.
  static bool IsUserClockInThePast(const base::Time& time_now);

  // Returns true if the system time is too far in the future or the user is
  // using a version of Chrome which is more than 1 year old.
  static bool IsUserClockInTheFuture(const base::Time& time_now);

  static bool IsWindowsVersionSP3OrLower();

  // A function which calculates the severity score when the ssl error is
  // CERT_DATE_INVALID, returns a score between 0.0 and 1.0, higher values
  // being more severe, indicating how severe the certificate's invalid
  // date error is.
  float InvalidDateSeverityScore(int cert_error) const;

  // A function which calculates the severity score when the ssl error is
  // when the SSL error is |CERT_COMMON_NAME_INVALID|, returns a score between
  // between 0.0 and 1.0, higher values being more severe, indicating how
  // severe the certificate's common name invalid error is.
  float InvalidCommonNameSeverityScore(int cert_error) const;

  void RecordUMAStatistics(bool overridable, int cert_error);
  base::TimeDelta TimePassedSinceExpiry() const;

 private:
  FRIEND_TEST_ALL_PREFIXES(SSLErrorClassificationTest, TestDateInvalidScore);
  FRIEND_TEST_ALL_PREFIXES(SSLErrorClassificationTest, TestNameMismatch);
  FRIEND_TEST_ALL_PREFIXES(SSLErrorClassificationTest,
                           TestHostNameHasKnownTLD);

  typedef std::vector<std::string> Tokens;

  // Returns true if the hostname has a known Top Level Domain.
  static bool IsHostNameKnownTLD(const std::string& host_name);

  // Returns true if the site's hostname differs from one of the DNS
  // names in the certificate (CN or SANs) only by the presence or
  // absence of the single-label prefix "www". E.g.:
  //
  //     www.example.com ~ example.com -> true
  //     example.com ~ www.example.com -> true
  //     www.food.example.com ~ example.com -> false
  //     mail.example.com ~ example.com -> false
  bool IsWWWSubDomainMatch() const;

  // Returns true if |child| is a subdomain of any of the |potential_parents|.
  bool NameUnderAnyNames(const Tokens& child,
                        const std::vector<Tokens>& potential_parents) const;

  // Returns true if any of the |potential_children| is a subdomain of the
  // |parent|. The inverse case should be treated carefully as this is most
  // likely a MITM attack. We don't want foo.appspot.com to be able to MITM for
  // appspot.com.
  bool AnyNamesUnderName(const std::vector<Tokens>& potential_children,
                        const Tokens& parent) const;

  // Returns true if |hostname| is too broad for the scope of a wildcard
  // certificate. E.g.:
  //
  //     a.b.example.com ~ *.example.com --> true
  //     b.example.com ~ *.example.com --> false
  bool IsSubDomainOutsideWildcard(const Tokens& hostname) const;

  // Returns true if the certificate is a shared certificate. Note - This
  // function should be used with caution (only for UMA histogram) as an
  // attacker could easily get a certificate with more than 5 names in the SAN
  // fields.
  bool IsCertLikelyFromMultiTenantHosting() const;

  float CalculateScoreTimePassedSinceExpiry() const;

  static std::vector<Tokens> GetTokenizedDNSNames(
      const std::vector<std::string>& dns_names);

  // If |potential_subdomain| is a subdomain of |parent|, returns the
  // number of DNS labels by which |potential_subdomain| is under
  // |parent|. Otherwise, returns 0.
  //
  // For example,
  //
  //   FindSubDomainDifference(Tokenize("a.b.example.com"),
  //                           Tokenize("example.com"))
  // --> 2.
  size_t FindSubDomainDifference(const Tokens& potential_subdomain,
                                 const Tokens& parent) const;

  static Tokens Tokenize(const std::string& name);

  // This stores the current time.
  base::Time current_time_;

  const GURL& request_url_;

  // This stores the certificate.
  const net::X509Certificate& cert_;
};

#endif  // CHROME_BROWSER_SSL_SSL_ERROR_CLASSIFICATION_H_