1 // Copyright (c) 2011 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 "chrome/browser/ssl_client_certificate_selector.h" 6 7 #include <windows.h> 8 #include <cryptuiapi.h> 9 #pragma comment(lib, "cryptui.lib") 10 11 #include "base/string_util.h" 12 #include "base/utf_string_conversions.h" 13 #include "chrome/browser/ssl/ssl_client_auth_handler.h" 14 #include "chrome/browser/ui/browser_list.h" 15 #include "chrome/browser/ui/browser_window.h" 16 #include "content/browser/tab_contents/tab_contents.h" 17 #include "grit/generated_resources.h" 18 #include "net/url_request/url_request.h" 19 #include "ui/base/l10n/l10n_util.h" 20 21 namespace browser { 22 23 void ShowSSLClientCertificateSelector( 24 TabContents* parent, 25 net::SSLCertRequestInfo* cert_request_info, 26 SSLClientAuthHandler* delegate) { 27 // TODO(jcampan): replace this with our own cert selection dialog. 28 // CryptUIDlgSelectCertificateFromStore is blocking (but still processes 29 // Windows messages), which is scary. 30 // 31 // TODO(davidben): Make this dialog tab-modal to the 32 // TabContents. This depends on the above TODO. 33 HCERTSTORE client_certs = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 34 0, NULL); 35 BOOL ok; 36 for (size_t i = 0; i < cert_request_info->client_certs.size(); ++i) { 37 PCCERT_CONTEXT cc = cert_request_info->client_certs[i]->os_cert_handle(); 38 ok = CertAddCertificateContextToStore(client_certs, cc, 39 CERT_STORE_ADD_ALWAYS, NULL); 40 DCHECK(ok); 41 } 42 43 std::wstring title = 44 UTF16ToWide(l10n_util::GetStringUTF16(IDS_CLIENT_CERT_DIALOG_TITLE)); 45 std::wstring text = UTF16ToWide(l10n_util::GetStringFUTF16( 46 IDS_CLIENT_CERT_DIALOG_TEXT, 47 ASCIIToUTF16(cert_request_info->host_and_port))); 48 PCCERT_CONTEXT cert_context = CryptUIDlgSelectCertificateFromStore( 49 client_certs, parent->GetMessageBoxRootWindow(), 50 title.c_str(), text.c_str(), 0, 0, NULL); 51 52 net::X509Certificate* cert = NULL; 53 if (cert_context) { 54 for (size_t i = 0; i < cert_request_info->client_certs.size(); ++i) { 55 net::X509Certificate* client_cert = cert_request_info->client_certs[i]; 56 if (net::X509Certificate::IsSameOSCert(cert_context, 57 client_cert->os_cert_handle())) { 58 cert = client_cert; 59 break; 60 } 61 } 62 DCHECK(cert != NULL); 63 net::X509Certificate::FreeOSCertHandle(cert_context); 64 } 65 66 ok = CertCloseStore(client_certs, CERT_CLOSE_STORE_CHECK_FLAG); 67 DCHECK(ok); 68 69 delegate->CertificateSelected(cert); 70 } 71 72 } // namespace browser 73