summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorsnej@chromium.org <snej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-02 17:47:02 +0000
committersnej@chromium.org <snej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-02 17:47:02 +0000
commitcdafbff7b3e83702c20b0f754a6d27159b78c06c (patch)
tree5b66619f7822e7189e8cc3287365ed49808d3c72 /chrome
parent078a10a1c64458e5f5c4fdf57edbbc935dd145ca (diff)
downloadchromium_src-cdafbff7b3e83702c20b0f754a6d27159b78c06c.zip
chromium_src-cdafbff7b3e83702c20b0f754a6d27159b78c06c.tar.gz
chromium_src-cdafbff7b3e83702c20b0f754a6d27159b78c06c.tar.bz2
Mac: implement <keygen> support, including adding generated cert to the Keychain.
BUG=34607 TEST=KeygenHandlerTest.SmokeTest Review URL: http://codereview.chromium.org/652137 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40387 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/generated_resources.grd14
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc21
-rw-r--r--chrome/browser/renderer_host/x509_user_cert_resource_handler.cc14
-rw-r--r--chrome/browser/ssl/ssl_add_cert_handler.cc69
-rw-r--r--chrome/browser/ssl/ssl_add_cert_handler.h50
-rw-r--r--chrome/browser/ssl/ssl_add_cert_handler_mac.mm88
-rwxr-xr-xchrome/chrome_browser.gypi3
7 files changed, 251 insertions, 8 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 6ba6970..bc8b8c1 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -2941,6 +2941,20 @@ each locale. -->
&amp;View
</message>
+ <!-- Add Client Certificate Dialog -->
+ <message name="IDS_ADD_CERT_DIALOG_ADD" desc="Title of the button that adds the certificate in the Add Client Certificate dialog">
+ Add Certificate
+ </message>
+ <message name="IDS_ADD_CERT_FAILURE_TITLE" desc="Title of add-certificate error dialog">
+ Client Certificate Error
+ </message>
+ <message name="IDS_ADD_CERT_ERR_INVALID_CERT" desc="Error message when the server returns an invalid client certificate after key generation">
+ The server returned an invalid client certificate.
+ </message>
+ <message name="IDS_ADD_CERT_ERR_FAILED" desc="Generic error message for a failure to add the generated certificate to the cert store/keychain">
+ There was an error while trying to store the client certificate.
+ </message>
+
<!-- Basic Auth Dialog -->
<message name="IDS_LOGIN_DIALOG_TITLE" desc="String to be displayed in the title bar of the login prompt dialog">
Authentication Required
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index b7c75e4..94f60a8 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -1332,10 +1332,23 @@ void ResourceMessageFilter::OnKeygen(uint32 key_size_index,
const std::string& challenge_string,
const GURL& url,
std::string* signed_public_key) {
- scoped_ptr<net::KeygenHandler> keygen_handler(
- new net::KeygenHandler(key_size_index,
- challenge_string));
- *signed_public_key = keygen_handler->GenKeyAndSignChallenge();
+ // Map displayed strings indicating level of keysecurity in the <keygen>
+ // menu to the key size in bits. (See SSLKeyGeneratorChromium.cpp in WebCore.)
+ int key_size_in_bits;
+ switch (key_size_index) {
+ case 0:
+ key_size_in_bits = 2048;
+ break;
+ case 1:
+ key_size_in_bits = 1024;
+ break;
+ default:
+ DCHECK(false) << "Illegal key_size_index " << key_size_index;
+ *signed_public_key = std::string();
+ return;
+ }
+ net::KeygenHandler keygen_handler(key_size_in_bits, challenge_string);
+ *signed_public_key = keygen_handler.GenKeyAndSignChallenge();
}
void ResourceMessageFilter::OnTranslateText(
diff --git a/chrome/browser/renderer_host/x509_user_cert_resource_handler.cc b/chrome/browser/renderer_host/x509_user_cert_resource_handler.cc
index 0c200a9..3dcc8ee 100644
--- a/chrome/browser/renderer_host/x509_user_cert_resource_handler.cc
+++ b/chrome/browser/renderer_host/x509_user_cert_resource_handler.cc
@@ -10,9 +10,9 @@
#include "chrome/browser/download/download_file.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
+#include "chrome/browser/ssl/ssl_add_cert_handler.h"
#include "chrome/common/resource_response.h"
#include "chrome/common/url_constants.h"
-#include "net/base/cert_database.h"
#include "net/base/io_buffer.h"
#include "net/base/mime_sniffer.h"
#include "net/base/mime_util.h"
@@ -91,12 +91,18 @@ bool X509UserCertResourceHandler::OnResponseCompleted(
int request_id,
const URLRequestStatus& urs,
const std::string& sec_info) {
+ if (urs.status() != URLRequestStatus::SUCCESS)
+ return false;
+
// TODO(gauravsh): Verify that 'request_id' was actually a keygen form post
// and only then import the certificate.
- scoped_ptr<net::CertDatabase> cert_db(new net::CertDatabase());
AssembleResource();
-
- return cert_db->AddUserCert(resource_buffer_->data(), content_length_);
+ scoped_refptr<net::X509Certificate> cert =
+ net::X509Certificate::CreateFromBytes(resource_buffer_->data(),
+ content_length_);
+ // The handler will run the UI and delete itself when it's finished.
+ new SSLAddCertHandler(request_, cert);
+ return true;
}
void X509UserCertResourceHandler::OnRequestClosed() {
diff --git a/chrome/browser/ssl/ssl_add_cert_handler.cc b/chrome/browser/ssl/ssl_add_cert_handler.cc
new file mode 100644
index 0000000..8c75d7d
--- /dev/null
+++ b/chrome/browser/ssl/ssl_add_cert_handler.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ssl/ssl_add_cert_handler.h"
+
+#include "app/l10n_util.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/common/platform_util.h"
+#include "grit/generated_resources.h"
+#include "net/base/cert_database.h"
+#include "net/base/net_errors.h"
+#include "net/base/x509_certificate.h"
+#include "net/url_request/url_request.h"
+
+SSLAddCertHandler::SSLAddCertHandler(URLRequest* request,
+ net::X509Certificate* cert)
+ : cert_(cert) {
+ // Stay alive until the UI completes and Finished() is called.
+ AddRef();
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &SSLAddCertHandler::RunUI));
+}
+
+void SSLAddCertHandler::RunUI() {
+ int cert_error;
+ {
+ net::CertDatabase db;
+ cert_error = db.CheckUserCert(cert_);
+ }
+ if (cert_error != net::OK) {
+ // TODO(snej): Map cert_error to a more specific error message.
+ ShowError(l10n_util::GetStringUTF16(IDS_ADD_CERT_ERR_INVALID_CERT));
+ Finished(false);
+ return;
+ }
+ AskToAddCert();
+}
+
+#if !defined(OS_MACOSX)
+void SSLAddCertHandler::AskToAddCert() {
+ // TODO(snej): Someone should add Windows and GTK implementations with UI.
+ Finished(true);
+}
+#endif
+
+void SSLAddCertHandler::Finished(bool add_cert) {
+ if (add_cert) {
+ net::CertDatabase db;
+ int cert_error = db.AddUserCert(cert_);
+ if (cert_error != net::OK) {
+ // TODO(snej): Map cert_error to a more specific error message.
+ ShowError(l10n_util::GetStringUTF16(IDS_ADD_CERT_ERR_FAILED));
+ }
+ }
+ Release();
+}
+
+void SSLAddCertHandler::ShowError(const string16& error) {
+ Browser* browser = BrowserList::GetLastActive();
+ platform_util::SimpleErrorBox(
+ browser ? browser->window()->GetNativeHandle() : NULL,
+ l10n_util::GetStringUTF16(IDS_ADD_CERT_FAILURE_TITLE),
+ error);
+}
diff --git a/chrome/browser/ssl/ssl_add_cert_handler.h b/chrome/browser/ssl/ssl_add_cert_handler.h
new file mode 100644
index 0000000..0680128
--- /dev/null
+++ b/chrome/browser/ssl/ssl_add_cert_handler.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SSL_SSL_ADD_CERT_HANDLER_H_
+#define CHROME_BROWSER_SSL_SSL_ADD_CERT_HANDLER_H_
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "base/string16.h"
+
+namespace net {
+class X509Certificate;
+}
+class URLRequest;
+
+// This class handles adding a newly-generated client cert. It ensures there's a
+// private key for the cert, displays the cert to the user, and adds it upon
+// user approval.
+// It is self-owned and deletes itself when finished.
+class SSLAddCertHandler : public base::RefCountedThreadSafe<SSLAddCertHandler> {
+ public:
+ SSLAddCertHandler(URLRequest* request, net::X509Certificate* cert);
+
+ net::X509Certificate* cert() { return cert_; }
+
+ // The platform-specific code calls this when it's done, to clean up.
+ // If |addCert| is true, the cert will be added to the CertDatabase.
+ void Finished(bool add_cert);
+
+ private:
+ friend class base::RefCountedThreadSafe<SSLAddCertHandler>;
+
+ // Runs the user interface. Called on the UI thread. Calls AskToAddCert.
+ void RunUI();
+
+ // Platform-specific code that asks the user whether to add the cert.
+ // Called on the UI thread.
+ void AskToAddCert();
+
+ // Utility to display an error message in a dialog box.
+ void ShowError(const string16& error);
+
+ // The cert to add.
+ scoped_refptr<net::X509Certificate> cert_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLAddCertHandler);
+};
+
+#endif // CHROME_BROWSER_SSL_SSL_ADD_CERT_HANDLER_H_
diff --git a/chrome/browser/ssl/ssl_add_cert_handler_mac.mm b/chrome/browser/ssl/ssl_add_cert_handler_mac.mm
new file mode 100644
index 0000000..75b8142
--- /dev/null
+++ b/chrome/browser/ssl/ssl_add_cert_handler_mac.mm
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ssl_add_cert_handler.h"
+
+#include <SecurityInterface/SFCertificatePanel.h>
+#include <SecurityInterface/SFCertificateView.h>
+
+#include "app/l10n_util_mac.h"
+#include "base/scoped_nsobject.h"
+#include "chrome/common/logging_chrome.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_window.h"
+#include "grit/generated_resources.h"
+#include "net/base/x509_certificate.h"
+
+@interface SSLAddCertHandlerCocoa : NSObject
+{
+ scoped_refptr<SSLAddCertHandler> handler_;
+}
+
+- (id)initWithHandler:(SSLAddCertHandler*)handler;
+- (void)askToAddCert;
+@end
+
+
+void SSLAddCertHandler::AskToAddCert() {
+ [[[SSLAddCertHandlerCocoa alloc] initWithHandler: this] askToAddCert];
+ // The new object will release itself when the sheet ends.
+}
+
+
+// The actual implementation of the add-client-cert handler is an Obj-C class.
+@implementation SSLAddCertHandlerCocoa
+
+- (id)initWithHandler:(SSLAddCertHandler*)handler {
+ DCHECK(handler && handler->cert());
+ self = [super init];
+ if (self) {
+ handler_ = handler;
+ }
+ return self;
+}
+
+- (void)sheetDidEnd:(SFCertificatePanel*)panel
+ returnCode:(NSInteger)returnCode
+ context:(void*)context {
+ [panel orderOut:self];
+ [panel autorelease];
+ handler_->Finished(returnCode == NSOKButton);
+ [self release];
+}
+
+- (void)askToAddCert {
+ NSWindow* parentWindow = NULL;
+ Browser* browser = BrowserList::GetLastActive();
+ // TODO(snej): Can I get the Browser that issued the request?
+ if (browser) {
+ parentWindow = browser->window()->GetNativeHandle();
+ if ([parentWindow attachedSheet])
+ parentWindow = nil;
+ }
+
+ // Create the cert panel, which will be released in my -sheetDidEnd: method.
+ SFCertificatePanel* panel = [[SFCertificatePanel alloc] init];
+ [panel setDefaultButtonTitle:l10n_util::GetNSString(IDS_ADD_CERT_DIALOG_ADD)];
+ [panel setAlternateButtonTitle:l10n_util::GetNSString(IDS_CANCEL)];
+ SecCertificateRef cert = handler_->cert()->os_cert_handle();
+ NSArray* certs = [NSArray arrayWithObject: (id)cert];
+
+ if (parentWindow) {
+ // Open the cert panel as a sheet on the browser window.
+ [panel beginSheetForWindow:parentWindow
+ modalDelegate:self
+ didEndSelector:@selector(sheetDidEnd:returnCode:context:)
+ contextInfo:NULL
+ certificates:certs
+ showGroup:NO];
+ } else {
+ // No available browser window, so run independently as a (blocking) dialog.
+ int returnCode = [panel runModalForCertificates:certs showGroup:NO];
+ [self sheetDidEnd:panel returnCode:returnCode context:NULL];
+ }
+}
+
+@end
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index fe76e2e..001b67a 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1746,6 +1746,9 @@
'browser/spellchecker_mac.mm',
'browser/spellchecker_platform_engine.h',
'browser/spellchecker_win.cc',
+ 'browser/ssl/ssl_add_cert_handler.cc',
+ 'browser/ssl/ssl_add_cert_handler.h',
+ 'browser/ssl/ssl_add_cert_handler_mac.mm',
'browser/ssl/ssl_blocking_page.cc',
'browser/ssl/ssl_blocking_page.h',
'browser/ssl/ssl_cert_error_handler.cc',