blob: f04179bde502e093ad641f96079b2533582e143c [file] [log] [blame]
Bruno Rocha7f9aea22011-09-12 14:31:24 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
7
8#include <string>
9
10#include <base/basictypes.h>
11#include <curl/curl.h>
12#include <gtest/gtest_prod.h> // for FRIEND_TEST
13#include <openssl/ssl.h>
14
15class MetricsLibraryInterface;
16namespace chromeos_update_engine { class PrefsInterface; }
17
18namespace chromeos_update_engine {
19
20// Wrapper for openssl operations with the certificates.
21class OpenSSLWrapper {
22 public:
23 OpenSSLWrapper() {}
24 virtual ~OpenSSLWrapper() {}
25
26 // Takes an openssl X509_STORE_CTX, extracts the corresponding certificate
27 // from it and calculates its fingerprint (SHA256 digest). Returns true on
28 // success and false otherwise.
29 //
30 // |x509_ctx| is the pointer to the openssl object that holds the certificate.
31 // |out_depth| is the depth of the current certificate, in the certificate
32 // chain.
33 // |out_digest_length| is the length of the generated digest.
34 // |out_digest| is the byte array where the digest itself will be written.
35 // It should be big enough to hold a SHA1 digest (e.g. EVP_MAX_MD_SIZE).
36 virtual bool GetCertificateDigest(X509_STORE_CTX* x509_ctx,
37 int* out_depth,
38 unsigned int* out_digest_length,
39 unsigned char* out_digest) const;
40
41 private:
42 DISALLOW_COPY_AND_ASSIGN(OpenSSLWrapper);
43};
44
45// Responsible for checking whether update server certificates change, and
46// reporting to UMA when this happens. Since all state information is persisted,
47// and openssl forces us to use a static callback with no data pointer, this
48// class is entirely static.
49class CertificateChecker {
50 public:
51 // These values are used to generate the keys of files persisted via prefs.
52 // This means that changing these will cause loss of information on metrics
53 // reporting, during the transition.
54 enum ServerToCheck {
55 kUpdate = 0,
56 kDownload = 1,
57 kNone = 2 // This needs to be the last element. Changing its value is ok.
58 };
59
60 CertificateChecker() {}
61 virtual ~CertificateChecker() {}
62
63 // This callback is called by libcurl just before the initialization of an
64 // SSL connection after having processed all other SSL related options. Used
65 // to check if server certificates change. |ptr| is expected to be a
66 // pointer to a ServerToCheck.
67 static CURLcode ProcessSSLContext(CURL* curl_handle, SSL_CTX* ssl_ctx,
68 void* ptr);
69
70 // Flushes to UMA any certificate-related report that was persisted.
71 static void FlushReport();
72
73 // Setters.
74 static void set_metrics_lib(MetricsLibraryInterface* metrics_lib) {
75 metrics_lib_ = metrics_lib;
76 }
77
78 static void set_prefs(PrefsInterface* prefs) {
79 prefs_ = prefs;
80 }
81
82 static void set_openssl_wrapper(OpenSSLWrapper* openssl_wrapper) {
83 openssl_wrapper_ = openssl_wrapper;
84 }
85
86 private:
87 FRIEND_TEST(CertificateCheckerTest, NewCertificate);
88 FRIEND_TEST(CertificateCheckerTest, SameCertificate);
89 FRIEND_TEST(CertificateCheckerTest, ChangedCertificate);
90 FRIEND_TEST(CertificateCheckerTest, FailedCertificate);
91 FRIEND_TEST(CertificateCheckerTest, FlushReport);
92 FRIEND_TEST(CertificateCheckerTest, FlushNothingToReport);
93
94 // These callbacks are called by openssl after initial SSL verification. They
95 // are used to perform any additional security verification on the connection,
96 // but we use them here to get hold of the server certificate, in order to
97 // determine if it has changed since the last connection. Since openssl forces
98 // us to do this statically, we define two different callbacks for the two
99 // different official update servers, and only assign the correspondent one.
100 // The assigned callback is then called once per each certificate on the
101 // server and returns 1 for success and 0 for failure.
102 static int VerifySSLCallbackUpdateCheck(int preverify_ok,
103 X509_STORE_CTX* x509_ctx);
104 static int VerifySSLCallbackDownload(int preverify_ok,
105 X509_STORE_CTX* x509_ctx);
106
107 // Checks if server certificate for |server_to_check|, stored in |x509_ctx|,
108 // has changed since last connection to that same server. This is called by
109 // one of the two callbacks defined above. If certificate fails to check or
110 // changes, a report is generated and persisted, to be later sent by
111 // FlushReport. Returns true on success and false otherwise.
112 static bool CheckCertificateChange(ServerToCheck server_to_check,
113 int preverify_ok,
114 X509_STORE_CTX* x509_ctx);
115
116 // Metrics library used to report to UMA.
117 static MetricsLibraryInterface* metrics_lib_;
118
119 // Prefs used to store certificates and UMA reports.
120 static PrefsInterface* prefs_;
121
122 // The wrapper for openssl operations.
123 static OpenSSLWrapper* openssl_wrapper_;
124
125 DISALLOW_COPY_AND_ASSIGN(CertificateChecker);
126};
127
128} // namespace chromeos_update_engine
129
130#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_CERTIFICATE_CHECKER_H_