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.
5 #include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
10 #include "base/logging.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "net/base/crypto_module.h"
13 #include "net/cert/x509_certificate.h"
15 using content::BrowserThread
;
19 bool ShouldShowDialog(const net::CryptoModule
* module
) {
20 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
21 return (PK11_NeedLogin(module
->os_module_handle()) &&
22 !PK11_IsLoggedIn(module
->os_module_handle(), NULL
/* wincx */));
25 // Basically an asynchronous implementation of NSS's PK11_DoPassword.
26 // Note: This currently handles only the simple case. See the TODOs in
27 // GotPassword for what is yet unimplemented.
30 SlotUnlocker(const net::CryptoModuleList
& modules
,
31 chrome::CryptoModulePasswordReason reason
,
32 const net::HostPortPair
& server
,
33 gfx::NativeWindow parent
,
34 const base::Closure
& callback
);
39 void GotPassword(const std::string
& password
);
43 net::CryptoModuleList modules_
;
44 chrome::CryptoModulePasswordReason reason_
;
45 net::HostPortPair server_
;
46 gfx::NativeWindow parent_
;
47 base::Closure callback_
;
51 SlotUnlocker::SlotUnlocker(const net::CryptoModuleList
& modules
,
52 chrome::CryptoModulePasswordReason reason
,
53 const net::HostPortPair
& server
,
54 gfx::NativeWindow parent
,
55 const base::Closure
& callback
)
63 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
66 void SlotUnlocker::Start() {
67 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
69 for (; current_
< modules_
.size(); ++current_
) {
70 if (ShouldShowDialog(modules_
[current_
].get())) {
71 ShowCryptoModulePasswordDialog(
72 modules_
[current_
]->GetTokenName(),
77 base::Bind(&SlotUnlocker::GotPassword
, base::Unretained(this)));
84 void SlotUnlocker::GotPassword(const std::string
& password
) {
85 // TODO(mattm): PK11_DoPassword has something about PK11_Global.verifyPass.
87 // http://mxr.mozilla.org/mozilla/source/security/nss/lib/pk11wrap/pk11auth.c#577
89 if (password
.empty()) {
90 // User cancelled entering password. Oh well.
96 // TODO(mattm): handle protectedAuthPath
97 SECStatus rv
= PK11_CheckUserPassword(modules_
[current_
]->os_module_handle(),
99 if (rv
== SECWouldBlock
) {
100 // Incorrect password. Try again.
106 // TODO(mattm): PK11_DoPassword calls nssTrustDomain_UpdateCachedTokenCerts on
107 // non-friendly slots. How important is that?
109 // Correct password (SECSuccess) or too many attempts/other failure
110 // (SECFailure). Either way we're done with this slot.
115 void SlotUnlocker::Done() {
116 DCHECK_EQ(current_
, modules_
.size());
125 void UnlockSlotsIfNecessary(const net::CryptoModuleList
& modules
,
126 chrome::CryptoModulePasswordReason reason
,
127 const net::HostPortPair
& server
,
128 gfx::NativeWindow parent
,
129 const base::Closure
& callback
) {
130 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
131 for (size_t i
= 0; i
< modules
.size(); ++i
) {
132 if (ShouldShowDialog(modules
[i
].get())) {
133 (new SlotUnlocker(modules
, reason
, server
, parent
, callback
))->Start();
140 void UnlockCertSlotIfNecessary(net::X509Certificate
* cert
,
141 chrome::CryptoModulePasswordReason reason
,
142 const net::HostPortPair
& server
,
143 gfx::NativeWindow parent
,
144 const base::Closure
& callback
) {
145 net::CryptoModuleList modules
;
146 modules
.push_back(net::CryptoModule::CreateFromHandle(
147 cert
->os_cert_handle()->slot
));
148 UnlockSlotsIfNecessary(modules
, reason
, server
, parent
, callback
);
151 } // namespace chrome