12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ssl/ssl_add_certificate.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/basictypes.h" 846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/certificate_viewer.h" 1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/infobars/infobar_service.h" 1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/infobars/simple_alert_infobar_delegate.h" 1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/infobars/core/confirm_infobar_delegate.h" 1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/infobars/core/infobar.h" 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/browser/render_frame_host.h" 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/browser/web_contents.h" 1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "grit/theme_resources.h" 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/base/net_errors.h" 2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/cert/cert_database.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using content::BrowserThread; 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using content::RenderFrameHost; 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using content::WebContents; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chrome { 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace { 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class SSLAddCertificateInfoBarDelegate : public ConfirmInfoBarDelegate { 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public: 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Creates an SSL certificate enrollment result infobar and delegate. 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static void Create(InfoBarService* infobar_service, 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) net::X509Certificate* cert) { 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar( 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<ConfirmInfoBarDelegate>( 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new SSLAddCertificateInfoBarDelegate(cert)))); 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private: 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) explicit SSLAddCertificateInfoBarDelegate(net::X509Certificate* cert) 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : cert_(cert) {} 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual ~SSLAddCertificateInfoBarDelegate() {} 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // ConfirmInfoBarDelegate implementation: 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual int GetIconID() const OVERRIDE { 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(davidben): Use a more appropriate icon. 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return IDR_INFOBAR_SAVE_PASSWORD; 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual Type GetInfoBarType() const OVERRIDE { 5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return PAGE_ACTION_TYPE; 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual base::string16 GetMessageText() const OVERRIDE { 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(evanm): GetDisplayName should return UTF-16. 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return l10n_util::GetStringFUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL, 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::UTF8ToUTF16( 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) cert_->issuer().GetDisplayName())); 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual int GetButtons() const OVERRIDE { 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return BUTTON_OK; 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE { 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_EQ(BUTTON_OK, button); 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON); 7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual bool Accept() OVERRIDE { 7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WebContents* web_contents = 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) InfoBarService::WebContentsFromInfoBar(infobar()); 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ShowCertificateViewer(web_contents, 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) web_contents->GetTopLevelNativeWindow(), 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) cert_.get()); 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // It looks weird to hide the infobar just as the dialog opens. 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The certificate that was added. 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_refptr<net::X509Certificate> cert_; 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SSLAddCertificateInfoBarDelegate); 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ShowErrorInfoBar(int message_id, 9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int render_process_id, 9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int render_frame_id, 9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int cert_error) { 9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WebContents* web_contents = WebContents::FromRenderFrameHost( 9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RenderFrameHost::FromID(render_process_id, render_frame_id)); 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!web_contents) 9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(davidben): Use a more appropriate icon. 10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(davidben): Display a more user-friendly error string. 10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SimpleAlertInfoBarDelegate::Create( 10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) InfoBarService::FromWebContents(web_contents), 10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) IDR_INFOBAR_SAVE_PASSWORD, 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_INVALID_CERT, 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::IntToString16(-cert_error), 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::ASCIIToUTF16( 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) net::ErrorToString(cert_error))), 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) true); 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ShowSuccessInfoBar(int render_process_id, 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int render_frame_id, 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) net::X509Certificate* cert) { 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WebContents* web_contents = WebContents::FromRenderFrameHost( 11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RenderFrameHost::FromID(render_process_id, render_frame_id)); 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!web_contents) 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SSLAddCertificateInfoBarDelegate::Create( 12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) InfoBarService::FromWebContents(web_contents), cert); 12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} // namespace 12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SSLAddCertificate( 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::CertificateMimeType cert_type, 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const void* cert_data, 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t cert_size, 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int render_process_id, 13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int render_frame_id) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Chromium only supports X.509 User certificates on non-Android 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // platforms. Note that this method should not be called for other 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // certificate mime types. 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cert_type != net::CERTIFICATE_MIME_TYPE_X509_USER_CERT) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<net::X509Certificate> cert; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cert_data != NULL) { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cert = net::X509Certificate::CreateFromBytes( 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<const char*>(cert_data), cert_size); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // NOTE: Passing a NULL cert pointer if |cert_data| was NULL is 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // intentional here. 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Check if we have a corresponding private key. 14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int cert_error = net::CertDatabase::GetInstance()->CheckUserCert(cert.get()); 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (cert_error != net::OK) { 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG_IF(ERROR, cert_error == net::ERR_NO_PRIVATE_KEY_FOR_CERT) 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << "No corresponding private key in store for cert: " 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << (cert.get() ? cert->subject().GetDisplayName() : "NULL"); 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::PostTask( 15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::UI, FROM_HERE, 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&ShowErrorInfoBar, IDS_ADD_CERT_ERR_INVALID_CERT, 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) render_process_id, render_frame_id, cert_error)); 15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Install it. 16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) cert_error = net::CertDatabase::GetInstance()->AddUserCert(cert.get()); 16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Show the appropriate infobar. 16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (cert_error != net::OK) { 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::PostTask( 16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::UI, FROM_HERE, 16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&ShowErrorInfoBar, IDS_ADD_CERT_ERR_FAILED, 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) render_process_id, render_frame_id, cert_error)); 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } else { 16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::PostTask( 17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::UI, FROM_HERE, 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&ShowSuccessInfoBar, 17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) render_process_id, render_frame_id, cert)); 17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace chrome 177