Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: chromeos/network/network_cert_handler.cc

Issue 20087002: Add migration from CaCert NSS nicknames to PEM. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium 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 #include "chromeos/network/network_cert_handler.h"
6
7 #include <cert.h>
8 #include <string>
9
10 #include "base/location.h"
11 #include "base/metrics/histogram.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13 #include "chromeos/dbus/shill_service_client.h"
14 #include "chromeos/network/network_handler_callbacks.h"
15 #include "chromeos/network/network_state.h"
16 #include "chromeos/network/network_state_handler.h"
17 #include "dbus/object_path.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
19
20 namespace chromeos {
21
22 namespace {
23
24 typedef std::vector<std::string> Nicknames;
pneubeck (no reviews) 2013/07/29 08:41:39 Not used, to be removed.
pneubeck (no reviews) 2013/07/29 13:15:08 Done.
25
26 enum UMANetworkType {
27 UMA_NETWORK_TYPE_EAP,
28 UMA_NETWORK_TYPE_OPENVPN,
29 UMA_NETWORK_TYPE_IPSEC,
30 UMA_NETWORK_TYPE_SIZE,
31 };
32
33 // Copied from x509_certificate_model_nss.cc
34 std::string GetNickname(const net::X509Certificate::OSCertHandle& cert_handle) {
35 if (!cert_handle->nickname)
36 return std::string();
37 std::string name = cert_handle->nickname;
38 // Hack copied from mozilla: Cut off text before first :, which seems to
39 // just be the token name.
40 size_t colon_pos = name.find(':');
41 if (colon_pos != std::string::npos)
42 name = name.substr(colon_pos + 1);
43 return name;
44 }
45
46 } // namespace
47
48 // Checks which of the given |networks| has one of the deprecated
49 // CaCertNssProperties set. If such a network already has a CaCertPEM property,
50 // then the NssProperty is cleared. Otherwise, the NssProperty is compared with
51 // the nickname of each certificate of |certs|. If a match is found, then the
52 // CaCertPemProperty is set and the NssProperty is cleared. Otherwise, the
53 // network is not modified.
54 class NetworkCertHandler::MigrationHelper
55 : public base::RefCounted<MigrationHelper> {
56 public:
57 MigrationHelper(const net::CertificateList& certs,
58 const base::WeakPtr<NetworkCertHandler>& cert_handler)
59 : certs_(certs),
60 cert_handler_(cert_handler) {
61 }
62
63 void Run(const NetworkStateHandler::NetworkStateList& networks) {
64 // Request properties for each network that has a CaCertNssProperty set
65 // according to the NetworkStateHandler.
66 for (NetworkStateHandler::NetworkStateList::const_iterator it =
67 networks.begin();
68 it != networks.end();
69 ++it) {
70 if (!(*it)->HasCACertNSS())
71 continue;
72 const std::string& service_path = (*it)->path();
73 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
74 dbus::ObjectPath(service_path),
75 base::Bind(
76 &MigrationHelper::GetPropertiesCallback, this, service_path));
77 }
78 }
79
80 void GetPropertiesCallback(const std::string& service_path,
Mattias Nissler (ping if slow) 2013/07/29 10:08:15 This does too damn much given the unsuspecting nam
pneubeck (no reviews) 2013/07/29 13:15:08 Done.
81 DBusMethodCallStatus call_status,
82 const base::DictionaryValue& properties) {
83 if (!cert_handler_) {
84 VLOG(2) << "NetworkCertHandler already destroyed. Aborting migration.";
85 return; // The CertHandler is destroyed, stop.
Mattias Nissler (ping if slow) 2013/07/29 10:08:15 Comment is redundant here, remove.
pneubeck (no reviews) 2013/07/29 13:15:08 Done.
86 }
87
88 if (call_status == DBUS_METHOD_CALL_FAILURE)
Mattias Nissler (ping if slow) 2013/07/29 10:08:15 Should this have a VLOG as well?
pneubeck (no reviews) 2013/07/29 13:15:08 Good point. Handling this error case like typical
89 return;
90
91 struct NssPem {
Mattias Nissler (ping if slow) 2013/07/29 10:08:15 static
pneubeck (no reviews) 2013/07/29 13:15:08 No, doesn't add anything: https://groups.google.co
92 const char* read_prefix;
93 const char* nss_key;
94 const char* pem_key;
95 UMANetworkType uma_type;
96 } const kNssPemMap[] = {
97 {NULL, flimflam::kEapCaCertNssProperty, shill::kEapCaCertPemProperty,
Mattias Nissler (ping if slow) 2013/07/29 10:08:15 I'm not entirely sure, but I think style guide / c
pneubeck (no reviews) 2013/07/29 13:15:08 optional, so I'd like to keep the automatic format
98 UMA_NETWORK_TYPE_EAP},
99 {flimflam::kProviderProperty, flimflam::kL2tpIpsecCaCertNssProperty,
100 shill::kL2tpIpsecCaCertPemProperty, UMA_NETWORK_TYPE_IPSEC},
101 {flimflam::kProviderProperty, flimflam::kOpenVPNCaCertNSSProperty,
102 shill::kOpenVPNCaCertPemProperty, UMA_NETWORK_TYPE_OPENVPN},
103 };
104
105 std::string nickname;
106 const base::ListValue* pem_property = NULL;
107 const NssPem* found_nss_pem = NULL;
108 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNssPemMap); ++i) {
109 const base::DictionaryValue* dict = &properties;
110 if (kNssPemMap[i].read_prefix) {
111 properties.GetDictionaryWithoutPathExpansion(kNssPemMap[i].read_prefix,
112 &dict);
113 if (!dict)
114 continue;
115 }
116 dict->GetStringWithoutPathExpansion(kNssPemMap[i].nss_key, &nickname);
117 if (!nickname.empty()) {
118 found_nss_pem = &kNssPemMap[i];
119 dict->GetListWithoutPathExpansion(kNssPemMap[i].pem_key, &pem_property);
120 break;
121 }
122 }
123
124 if (nickname.empty())
125 return; // Didn't find any nickname.
126
127 VLOG(2) << "Found NSS nickname to migrate. Property: "
128 << found_nss_pem->nss_key << ", network: " << service_path;
129 UMA_HISTOGRAM_ENUMERATION("Network.MigrationNssToPem",
130 found_nss_pem->uma_type,
131 UMA_NETWORK_TYPE_SIZE);
132
133 if (pem_property && !pem_property->empty()) {
134 // The PEM property exists already. We only have to clear the NSS
135 // property.
136 VLOG(2) << "PEM already exists, clear NSS property.";
Mattias Nissler (ping if slow) 2013/07/29 10:08:15 nit: s/clear/clearing/
pneubeck (no reviews) 2013/07/29 13:15:08 Done.
137 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
138 dbus::ObjectPath(service_path),
139 found_nss_pem->nss_key,
140 base::StringValue(std::string()),
141 base::Bind(&base::DoNothing),
142 base::Bind(&network_handler::ShillErrorCallbackFunction,
143 "MigrationHelper.ClearProperty failed",
144 service_path,
145 network_handler::ErrorCallback()));
146 CHECK(cert_handler_);
147 CHECK(cert_handler_->network_state_handler_);
148 cert_handler_->network_state_handler_
149 ->RequestUpdateForNetwork(service_path);
150 return;
151 }
152
153 scoped_refptr<net::X509Certificate> cert;
154 for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end();
155 ++it) {
156 if (nickname == GetNickname((*it)->os_cert_handle())) {
157 cert = *it;
158 break;
159 }
160 }
161
162 if (!cert) {
163 VLOG(2) << "No matching cert found.";
164 return; // Didn't find a matching certificate.
Mattias Nissler (ping if slow) 2013/07/29 10:08:15 nit: remove redundant comment
pneubeck (no reviews) 2013/07/29 13:15:08 Done.
165 }
166
167 std::string pem_encoded;
168 if (!net::X509Certificate::GetPEMEncoded(cert->os_cert_handle(),
169 &pem_encoded)) {
170 LOG(ERROR) << "PEM encoding failed.";
171 return; // PEM encoding failed.
Mattias Nissler (ping if slow) 2013/07/29 10:08:15 nit: remove redundant comment
pneubeck (no reviews) 2013/07/29 13:15:08 Done.
172 }
173
174 base::DictionaryValue new_properties;
175 new_properties.SetStringWithoutPathExpansion(found_nss_pem->nss_key,
176 std::string());
177 scoped_ptr<base::ListValue> ca_cert_pems(new base::ListValue);
178 ca_cert_pems->AppendString(pem_encoded);
179 new_properties.SetWithoutPathExpansion(found_nss_pem->pem_key,
180 ca_cert_pems.release());
181
182 DBusThreadManager::Get()->GetShillServiceClient()
183 ->SetProperties(dbus::ObjectPath(service_path),
184 new_properties,
185 base::Bind(&base::DoNothing),
186 base::Bind(&network_handler::ShillErrorCallbackFunction,
187 "MigrationHelper.SetProperties failed",
188 service_path,
189 network_handler::ErrorCallback()));
190 cert_handler_->network_state_handler_
191 ->RequestUpdateForNetwork(service_path);
192 }
193
194 private:
195 friend class base::RefCounted<MigrationHelper>;
196 virtual ~MigrationHelper() {
197 }
198
199 net::CertificateList certs_;
200 base::WeakPtr<NetworkCertHandler> cert_handler_;
201 };
202
203 NetworkCertHandler::NetworkCertHandler()
204 : network_state_handler_(NULL), weak_ptr_factory_(this) {}
205
206 NetworkCertHandler::~NetworkCertHandler() {
207 if (network_state_handler_)
208 network_state_handler_->RemoveObserver(this, FROM_HERE);
209 if (CertLoader::IsInitialized())
210 CertLoader::Get()->RemoveObserver(this);
211 }
212
213 void NetworkCertHandler::Init(NetworkStateHandler* network_state_handler) {
214 DCHECK(network_state_handler);
215 network_state_handler_ = network_state_handler;
216 network_state_handler_->AddObserver(this, FROM_HERE);
217
218 DCHECK(CertLoader::IsInitialized());
219 CertLoader::Get()->AddObserver(this);
220 }
221
222 void NetworkCertHandler::NetworkListChanged() {
223 if (!CertLoader::Get()->certificates_loaded()) {
224 VLOG(2) << "Certs not loaded yet.";
225 return;
226 }
227 // Run the migration process from deprecated CaCertNssProperties to CaCertPem.
228 VLOG(2) << "Start NSS nickname to PEM migration.";
229 scoped_refptr<MigrationHelper> helper(new MigrationHelper(
230 CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr()));
231 NetworkStateHandler::NetworkStateList networks;
232 network_state_handler_->GetNetworkList(&networks);
233 helper->Run(networks);
234 }
235
236 void NetworkCertHandler::OnCertificatesLoaded(
237 const net::CertificateList& cert_list,
238 bool initial_load) {
239 // Maybe there are networks referring to certs (by NSS nickname) that were not
240 // loaded before but are now.
241 NetworkListChanged();
242 }
243
244 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698