OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ssl_client_certificate_selector.h" | 5 #include "chrome/browser/ssl_client_certificate_selector.h" |
6 | 6 |
7 #include <cert.h> | |
8 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
9 | 8 |
10 #include <string> | 9 #include <string> |
11 #include <vector> | 10 #include <vector> |
12 | 11 |
13 #include "app/gtk_signal.h" | 12 #include "app/gtk_signal.h" |
14 #include "app/l10n_util.h" | 13 #include "app/l10n_util.h" |
15 #include "base/i18n/time_formatting.h" | 14 #include "base/i18n/time_formatting.h" |
16 #include "base/logging.h" | 15 #include "base/logging.h" |
17 #include "base/nss_util.h" | 16 #include "base/nss_util.h" |
18 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
19 #include "chrome/browser/certificate_viewer.h" | 18 #include "chrome/browser/certificate_viewer.h" |
20 #include "chrome/browser/gtk/constrained_window_gtk.h" | 19 #include "chrome/browser/gtk/constrained_window_gtk.h" |
21 #include "chrome/browser/gtk/gtk_util.h" | 20 #include "chrome/browser/gtk/gtk_util.h" |
22 #include "chrome/browser/gtk/owned_widget_gtk.h" | 21 #include "chrome/browser/gtk/owned_widget_gtk.h" |
23 #include "chrome/browser/ssl/ssl_client_auth_handler.h" | 22 #include "chrome/browser/ssl/ssl_client_auth_handler.h" |
24 #include "chrome/browser/tab_contents/tab_contents.h" | 23 #include "chrome/browser/tab_contents/tab_contents.h" |
25 #include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h" | 24 #include "chrome/common/net/x509_certificate_model.h" |
26 #include "chrome/third_party/mozilla_security_manager/nsNSSCertificate.h" | |
27 #include "chrome/third_party/mozilla_security_manager/nsUsageArrayHelper.h" | |
28 #include "gfx/native_widget_types.h" | 25 #include "gfx/native_widget_types.h" |
29 #include "grit/generated_resources.h" | 26 #include "grit/generated_resources.h" |
30 #include "net/base/x509_certificate.h" | 27 #include "net/base/x509_certificate.h" |
31 | 28 |
32 // PSM = Mozilla's Personal Security Manager. | |
33 namespace psm = mozilla_security_manager; | |
34 | |
35 namespace { | 29 namespace { |
36 | 30 |
37 enum { | 31 enum { |
38 RESPONSE_SHOW_CERT_INFO = 1, | 32 RESPONSE_SHOW_CERT_INFO = 1, |
39 }; | 33 }; |
40 | 34 |
41 /////////////////////////////////////////////////////////////////////////////// | 35 /////////////////////////////////////////////////////////////////////////////// |
42 // SSLClientCertificateSelector | 36 // SSLClientCertificateSelector |
43 | 37 |
44 class SSLClientCertificateSelector : public ConstrainedDialogDelegate { | 38 class SSLClientCertificateSelector : public ConstrainedDialogDelegate { |
45 public: | 39 public: |
46 explicit SSLClientCertificateSelector( | 40 explicit SSLClientCertificateSelector( |
47 TabContents* parent, | 41 TabContents* parent, |
48 net::SSLCertRequestInfo* cert_request_info, | 42 net::SSLCertRequestInfo* cert_request_info, |
49 SSLClientAuthHandler* delegate); | 43 SSLClientAuthHandler* delegate); |
50 ~SSLClientCertificateSelector(); | 44 ~SSLClientCertificateSelector(); |
51 | 45 |
52 void Show(); | 46 void Show(); |
53 | 47 |
54 // ConstrainedDialogDelegate implementation: | 48 // ConstrainedDialogDelegate implementation: |
55 virtual GtkWidget* GetWidgetRoot() { return root_widget_.get(); } | 49 virtual GtkWidget* GetWidgetRoot() { return root_widget_.get(); } |
56 virtual void DeleteDelegate() { delete this; } | 50 virtual void DeleteDelegate() { delete this; } |
57 | 51 |
58 private: | 52 private: |
59 void PopulateCerts(); | 53 void PopulateCerts(); |
60 | 54 |
61 net::X509Certificate* GetSelectedCert(); | 55 net::X509Certificate* GetSelectedCert(); |
62 | 56 |
63 static std::string FormatComboBoxText(CERTCertificate* cert, | 57 static std::string FormatComboBoxText( |
64 const char* nickname); | 58 net::X509Certificate::OSCertHandle cert, |
65 static std::string FormatDetailsText(CERTCertificate* cert); | 59 const std::string& nickname); |
| 60 static std::string FormatDetailsText( |
| 61 net::X509Certificate::OSCertHandle cert); |
66 | 62 |
67 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnComboBoxChanged); | 63 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnComboBoxChanged); |
68 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnViewClicked); | 64 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnViewClicked); |
69 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnCancelClicked); | 65 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnCancelClicked); |
70 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnOkClicked); | 66 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnOkClicked); |
71 CHROMEGTK_CALLBACK_1(SSLClientCertificateSelector, void, OnPromptShown, | 67 CHROMEGTK_CALLBACK_1(SSLClientCertificateSelector, void, OnPromptShown, |
72 GtkWidget*); | 68 GtkWidget*); |
73 | 69 |
74 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_; | 70 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_; |
75 | 71 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 SSLClientCertificateSelector::~SSLClientCertificateSelector() { | 180 SSLClientCertificateSelector::~SSLClientCertificateSelector() { |
185 root_widget_.Destroy(); | 181 root_widget_.Destroy(); |
186 } | 182 } |
187 | 183 |
188 void SSLClientCertificateSelector::Show() { | 184 void SSLClientCertificateSelector::Show() { |
189 DCHECK(!window_); | 185 DCHECK(!window_); |
190 window_ = parent_->CreateConstrainedDialog(this); | 186 window_ = parent_->CreateConstrainedDialog(this); |
191 } | 187 } |
192 | 188 |
193 void SSLClientCertificateSelector::PopulateCerts() { | 189 void SSLClientCertificateSelector::PopulateCerts() { |
194 CERTCertList* cert_list = CERT_NewCertList(); | 190 std::vector<std::string> nicknames; |
195 for (size_t i = 0; i < cert_request_info_->client_certs.size(); ++i) { | 191 x509_certificate_model::GetNicknameStringsFromCertList( |
196 CERT_AddCertToListTail( | 192 cert_request_info_->client_certs, |
197 cert_list, | 193 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_EXPIRED), |
198 CERT_DupCertificate( | 194 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_NOT_YET_VALID), |
199 cert_request_info_->client_certs[i]->os_cert_handle())); | 195 &nicknames); |
200 } | 196 |
201 // Would like to use CERT_GetCertNicknameWithValidity on each cert | 197 DCHECK_EQ(nicknames.size(), |
202 // individually instead of having to build a CERTCertList for this, but that | 198 cert_request_info_->client_certs.size()); |
203 // function is not exported. | |
204 CERTCertNicknames* nicknames = CERT_NicknameStringsFromCertList( | |
205 cert_list, | |
206 const_cast<char*>(l10n_util::GetStringUTF8( | |
207 IDS_CERT_SELECTOR_CERT_EXPIRED).c_str()), | |
208 const_cast<char*>(l10n_util::GetStringUTF8( | |
209 IDS_CERT_SELECTOR_CERT_NOT_YET_VALID).c_str())); | |
210 DCHECK_EQ(nicknames->numnicknames, | |
211 static_cast<int>(cert_request_info_->client_certs.size())); | |
212 | 199 |
213 for (size_t i = 0; i < cert_request_info_->client_certs.size(); ++i) { | 200 for (size_t i = 0; i < cert_request_info_->client_certs.size(); ++i) { |
214 CERTCertificate* cert = | 201 net::X509Certificate::OSCertHandle cert = |
215 cert_request_info_->client_certs[i]->os_cert_handle(); | 202 cert_request_info_->client_certs[i]->os_cert_handle(); |
216 | 203 |
217 details_strings_.push_back(FormatDetailsText(cert)); | 204 details_strings_.push_back(FormatDetailsText(cert)); |
218 | 205 |
219 gtk_combo_box_append_text( | 206 gtk_combo_box_append_text( |
220 GTK_COMBO_BOX(cert_combo_box_), | 207 GTK_COMBO_BOX(cert_combo_box_), |
221 FormatComboBoxText(cert, nicknames->nicknames[i]).c_str()); | 208 FormatComboBoxText(cert, nicknames[i]).c_str()); |
222 } | 209 } |
223 | 210 |
224 CERT_FreeNicknames(nicknames); | |
225 CERT_DestroyCertList(cert_list); | |
226 | |
227 // Auto-select the first cert. | 211 // Auto-select the first cert. |
228 gtk_combo_box_set_active(GTK_COMBO_BOX(cert_combo_box_), 0); | 212 gtk_combo_box_set_active(GTK_COMBO_BOX(cert_combo_box_), 0); |
229 } | 213 } |
230 | 214 |
231 net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() { | 215 net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() { |
232 int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(cert_combo_box_)); | 216 int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(cert_combo_box_)); |
233 if (selected >= 0 && | 217 if (selected >= 0 && |
234 selected < static_cast<int>( | 218 selected < static_cast<int>( |
235 cert_request_info_->client_certs.size())) | 219 cert_request_info_->client_certs.size())) |
236 return cert_request_info_->client_certs[selected]; | 220 return cert_request_info_->client_certs[selected]; |
237 return NULL; | 221 return NULL; |
238 } | 222 } |
239 | 223 |
240 // static | 224 // static |
241 std::string SSLClientCertificateSelector::FormatComboBoxText( | 225 std::string SSLClientCertificateSelector::FormatComboBoxText( |
242 CERTCertificate* cert, const char* nickname) { | 226 net::X509Certificate::OSCertHandle cert, const std::string& nickname) { |
243 std::string rv(nickname); | 227 std::string rv(nickname); |
244 char* serial_hex = CERT_Hexify(&cert->serialNumber, TRUE); | |
245 rv += " ["; | 228 rv += " ["; |
246 rv += serial_hex; | 229 rv += x509_certificate_model::GetSerialNumberHexified(cert, ""); |
247 rv += ']'; | 230 rv += ']'; |
248 PORT_Free(serial_hex); | |
249 return rv; | 231 return rv; |
250 } | 232 } |
251 | 233 |
252 // static | 234 // static |
253 std::string SSLClientCertificateSelector::FormatDetailsText( | 235 std::string SSLClientCertificateSelector::FormatDetailsText( |
254 CERTCertificate* cert) { | 236 net::X509Certificate::OSCertHandle cert) { |
255 std::string rv; | 237 std::string rv; |
256 | 238 |
257 rv += l10n_util::GetStringFUTF8(IDS_CERT_SUBJECTNAME_FORMAT, | 239 rv += l10n_util::GetStringFUTF8( |
258 UTF8ToUTF16(cert->subjectName)); | 240 IDS_CERT_SUBJECTNAME_FORMAT, |
| 241 UTF8ToUTF16(x509_certificate_model::GetSubjectName(cert)));; |
259 | 242 |
260 char* serial_hex = CERT_Hexify(&cert->serialNumber, TRUE); | |
261 rv += "\n "; | 243 rv += "\n "; |
262 rv += l10n_util::GetStringFUTF8(IDS_CERT_SERIAL_NUMBER_FORMAT, | 244 rv += l10n_util::GetStringFUTF8( |
263 UTF8ToUTF16(serial_hex)); | 245 IDS_CERT_SERIAL_NUMBER_FORMAT, |
264 PORT_Free(serial_hex); | 246 UTF8ToUTF16( |
| 247 x509_certificate_model::GetSerialNumberHexified(cert, ""))); |
265 | 248 |
266 PRTime issued, expires; | 249 base::Time issued, expires; |
267 if (CERT_GetCertTimes(cert, &issued, &expires) == SECSuccess) { | 250 if (x509_certificate_model::GetTimes(cert, &issued, &expires)) { |
268 string16 issued_str = WideToUTF16( | 251 string16 issued_str = WideToUTF16( |
269 base::TimeFormatShortDateAndTime(base::PRTimeToBaseTime(issued))); | 252 base::TimeFormatShortDateAndTime(issued)); |
270 string16 expires_str = WideToUTF16( | 253 string16 expires_str = WideToUTF16( |
271 base::TimeFormatShortDateAndTime(base::PRTimeToBaseTime(expires))); | 254 base::TimeFormatShortDateAndTime(expires)); |
272 rv += "\n "; | 255 rv += "\n "; |
273 rv += l10n_util::GetStringFUTF8(IDS_CERT_VALIDITY_RANGE_FORMAT, | 256 rv += l10n_util::GetStringFUTF8(IDS_CERT_VALIDITY_RANGE_FORMAT, |
274 issued_str, expires_str); | 257 issued_str, expires_str); |
275 } | 258 } |
276 | 259 |
277 std::vector<std::string> usages; | 260 std::vector<std::string> usages; |
278 psm::GetCertUsageStrings(cert, &usages); | 261 x509_certificate_model::GetUsageStrings(cert, &usages); |
279 if (usages.size()) { | 262 if (usages.size()) { |
280 rv += "\n "; | 263 rv += "\n "; |
281 rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_EXTENDED_KEY_USAGE_FORMAT, | 264 rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_EXTENDED_KEY_USAGE_FORMAT, |
282 UTF8ToUTF16(JoinString(usages, ','))); | 265 UTF8ToUTF16(JoinString(usages, ','))); |
283 } | 266 } |
284 | 267 |
285 SECItem key_usage; | 268 std::string key_usage_str = x509_certificate_model::GetKeyUsageString(cert); |
286 key_usage.data = NULL; | 269 if (!key_usage_str.empty()) { |
287 if (CERT_FindKeyUsageExtension(cert, &key_usage) == SECSuccess) { | 270 rv += "\n "; |
288 std::string key_usage_str = psm::ProcessKeyUsageBitString(&key_usage, ','); | 271 rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_KEY_USAGE_FORMAT, |
289 PORT_Free(key_usage.data); | 272 UTF8ToUTF16(key_usage_str)); |
290 if (!key_usage_str.empty()) { | |
291 rv += "\n "; | |
292 rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_KEY_USAGE_FORMAT, | |
293 UTF8ToUTF16(key_usage_str)); | |
294 } | |
295 } | 273 } |
296 | 274 |
297 std::vector<std::string> email_addresses; | 275 std::vector<std::string> email_addresses; |
298 for (const char* addr = CERT_GetFirstEmailAddress(cert); | 276 x509_certificate_model::GetEmailAddresses(cert, &email_addresses); |
299 addr; addr = CERT_GetNextEmailAddress(cert, addr)) { | |
300 // The first email addr (from Subject) may be duplicated in Subject | |
301 // Alternative Name, so check subsequent addresses are not equal to the | |
302 // first one before adding to the list. | |
303 if (!email_addresses.size() || email_addresses[0] != addr) | |
304 email_addresses.push_back(addr); | |
305 } | |
306 if (email_addresses.size()) { | 277 if (email_addresses.size()) { |
307 rv += "\n "; | 278 rv += "\n "; |
308 rv += l10n_util::GetStringFUTF8( | 279 rv += l10n_util::GetStringFUTF8( |
309 IDS_CERT_EMAIL_ADDRESSES_FORMAT, | 280 IDS_CERT_EMAIL_ADDRESSES_FORMAT, |
310 UTF8ToUTF16(JoinString(email_addresses, ','))); | 281 UTF8ToUTF16(JoinString(email_addresses, ','))); |
311 } | 282 } |
312 | 283 |
313 rv += '\n'; | 284 rv += '\n'; |
314 rv += l10n_util::GetStringFUTF8(IDS_CERT_ISSUERNAME_FORMAT, | 285 rv += l10n_util::GetStringFUTF8( |
315 UTF8ToUTF16(cert->issuerName)); | 286 IDS_CERT_ISSUERNAME_FORMAT, |
| 287 UTF8ToUTF16(x509_certificate_model::GetIssuerName(cert))); |
316 | 288 |
317 string16 token(UTF8ToUTF16(psm::GetCertTokenName(cert))); | 289 string16 token(UTF8ToUTF16(x509_certificate_model::GetTokenName(cert))); |
318 if (!token.empty()) { | 290 if (!token.empty()) { |
319 rv += '\n'; | 291 rv += '\n'; |
320 rv += l10n_util::GetStringFUTF8(IDS_CERT_TOKEN_FORMAT, token); | 292 rv += l10n_util::GetStringFUTF8(IDS_CERT_TOKEN_FORMAT, token); |
321 } | 293 } |
322 | 294 |
323 return rv; | 295 return rv; |
324 } | 296 } |
325 | 297 |
326 void SSLClientCertificateSelector::OnComboBoxChanged(GtkWidget* combo_box) { | 298 void SSLClientCertificateSelector::OnComboBoxChanged(GtkWidget* combo_box) { |
327 int selected = gtk_combo_box_get_active( | 299 int selected = gtk_combo_box_get_active( |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 void ShowSSLClientCertificateSelector( | 346 void ShowSSLClientCertificateSelector( |
375 TabContents* parent, | 347 TabContents* parent, |
376 net::SSLCertRequestInfo* cert_request_info, | 348 net::SSLCertRequestInfo* cert_request_info, |
377 SSLClientAuthHandler* delegate) { | 349 SSLClientAuthHandler* delegate) { |
378 (new SSLClientCertificateSelector(parent, | 350 (new SSLClientCertificateSelector(parent, |
379 cert_request_info, | 351 cert_request_info, |
380 delegate))->Show(); | 352 delegate))->Show(); |
381 } | 353 } |
382 | 354 |
383 } // namespace browser | 355 } // namespace browser |
OLD | NEW |