| 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 |