OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/ui/crypto_module_password_dialog.h" | 5 #include "chrome/browser/ui/crypto_module_password_dialog.h" |
6 | 6 |
7 #include <pk11pub.h> | 7 #include <pk11pub.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "chrome/browser/browser_thread.h" | 10 #include "chrome/browser/browser_thread.h" |
11 #include "net/base/crypto_module.h" | 11 #include "net/base/crypto_module.h" |
12 #include "net/base/x509_certificate.h" | 12 #include "net/base/x509_certificate.h" |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 bool ShouldShowDialog(const net::CryptoModule* module) { | |
17 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc. | |
18 return (PK11_NeedLogin(module->os_module_handle()) && | |
19 !PK11_IsLoggedIn(module->os_module_handle(), NULL /* wincx */)); | |
20 } | |
21 | |
16 // Basically an asynchronous implementation of NSS's PK11_DoPassword. | 22 // Basically an asynchronous implementation of NSS's PK11_DoPassword. |
17 // Note: This currently handles only the simple case. See the TODOs in | 23 // Note: This currently handles only the simple case. See the TODOs in |
18 // GotPassword for what is yet unimplemented. | 24 // GotPassword for what is yet unimplemented. |
19 class SlotUnlocker { | 25 class SlotUnlocker { |
20 public: | 26 public: |
21 SlotUnlocker(net::CryptoModule* module, | 27 SlotUnlocker(const net::CryptoModuleList& modules, |
22 browser::CryptoModulePasswordReason reason, | 28 browser::CryptoModulePasswordReason reason, |
23 const std::string& host, | 29 const std::string& host, |
24 Callback0::Type* callback); | 30 Callback0::Type* callback); |
25 | 31 |
26 void Start(); | 32 void Start(); |
27 | 33 |
28 private: | 34 private: |
29 void GotPassword(const char* password); | 35 void GotPassword(const char* password); |
30 void Done(); | 36 void Done(); |
31 | 37 |
32 scoped_refptr<net::CryptoModule> module_; | 38 size_t cur_; |
wtc
2011/03/02 03:33:28
Nit: the Style Guide seems to discourage this kind
mattm
2011/03/05 02:16:32
yeah, changed to current_
| |
39 net::CryptoModuleList modules_; | |
33 browser::CryptoModulePasswordReason reason_; | 40 browser::CryptoModulePasswordReason reason_; |
34 std::string host_; | 41 std::string host_; |
35 Callback0::Type* callback_; | 42 Callback0::Type* callback_; |
36 PRBool retry_; | 43 PRBool retry_; |
37 }; | 44 }; |
38 | 45 |
39 SlotUnlocker::SlotUnlocker(net::CryptoModule* module, | 46 SlotUnlocker::SlotUnlocker(const net::CryptoModuleList& modules, |
40 browser::CryptoModulePasswordReason reason, | 47 browser::CryptoModulePasswordReason reason, |
41 const std::string& host, | 48 const std::string& host, |
42 Callback0::Type* callback) | 49 Callback0::Type* callback) |
43 : module_(module), | 50 : cur_(0), |
51 modules_(modules), | |
44 reason_(reason), | 52 reason_(reason), |
45 host_(host), | 53 host_(host), |
46 callback_(callback), | 54 callback_(callback), |
47 retry_(PR_FALSE) { | 55 retry_(PR_FALSE) { |
48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 56 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
49 } | 57 } |
50 | 58 |
51 void SlotUnlocker::Start() { | 59 void SlotUnlocker::Start() { |
52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
53 | 61 |
54 ShowCryptoModulePasswordDialog( | 62 for (; cur_ < modules_.size(); ++cur_) { |
55 module_->GetTokenName(), | 63 if (ShouldShowDialog(modules_[cur_].get())) { |
56 retry_, | 64 ShowCryptoModulePasswordDialog( |
57 reason_, | 65 modules_[cur_]->GetTokenName(), |
58 host_, | 66 retry_, |
59 NewCallback(this, &SlotUnlocker::GotPassword)); | 67 reason_, |
68 host_, | |
69 NewCallback(this, &SlotUnlocker::GotPassword)); | |
70 return; | |
71 } | |
72 } | |
73 Done(); | |
60 } | 74 } |
61 | 75 |
62 void SlotUnlocker::GotPassword(const char* password) { | 76 void SlotUnlocker::GotPassword(const char* password) { |
63 // TODO(mattm): PK11_DoPassword has something about PK11_Global.verifyPass. | 77 // TODO(mattm): PK11_DoPassword has something about PK11_Global.verifyPass. |
64 // Do we need it? | 78 // Do we need it? |
65 // http://mxr.mozilla.org/mozilla/source/security/nss/lib/pk11wrap/pk11auth.c# 577 | 79 // http://mxr.mozilla.org/mozilla/source/security/nss/lib/pk11wrap/pk11auth.c# 577 |
66 | 80 |
67 if (!password) { | 81 if (!password) { |
68 // User cancelled entering password. Oh well. | 82 // User cancelled entering password. Oh well. |
69 Done(); | 83 ++cur_; |
84 Start(); | |
70 return; | 85 return; |
71 } | 86 } |
72 | 87 |
73 // TODO(mattm): handle protectedAuthPath | 88 // TODO(mattm): handle protectedAuthPath |
74 SECStatus rv = PK11_CheckUserPassword(module_->os_module_handle(), | 89 SECStatus rv = PK11_CheckUserPassword(modules_[cur_]->os_module_handle(), |
75 password); | 90 password); |
76 if (rv == SECWouldBlock) { | 91 if (rv == SECWouldBlock) { |
77 // Incorrect password. Try again. | 92 // Incorrect password. Try again. |
78 retry_ = PR_TRUE; | 93 retry_ = PR_TRUE; |
79 Start(); | 94 Start(); |
80 return; | 95 return; |
81 } | 96 } |
82 | 97 |
83 // TODO(mattm): PK11_DoPassword calls nssTrustDomain_UpdateCachedTokenCerts on | 98 // TODO(mattm): PK11_DoPassword calls nssTrustDomain_UpdateCachedTokenCerts on |
84 // non-friendly slots. How important is that? | 99 // non-friendly slots. How important is that? |
85 | 100 |
86 // Correct password (SECSuccess) or too many attempts/other failure | 101 // Correct password (SECSuccess) or too many attempts/other failure |
87 // (SECFailure). Either way we're done. | 102 // (SECFailure). Either way we're done with this slot. |
88 Done(); | 103 ++cur_; |
104 Start(); | |
89 } | 105 } |
90 | 106 |
91 void SlotUnlocker::Done() { | 107 void SlotUnlocker::Done() { |
108 DCHECK_EQ(cur_, modules_.size()); | |
92 callback_->Run(); | 109 callback_->Run(); |
93 delete this; | 110 delete this; |
94 } | 111 } |
95 | 112 |
96 } // namespace | 113 } // namespace |
97 | 114 |
98 namespace browser { | 115 namespace browser { |
99 | 116 |
100 void UnlockSlotIfNecessary(net::CryptoModule* module, | 117 void UnlockSlotsIfNecessary(const net::CryptoModuleList& modules, |
101 browser::CryptoModulePasswordReason reason, | 118 browser::CryptoModulePasswordReason reason, |
102 const std::string& host, | 119 const std::string& host, |
103 Callback0::Type* callback) { | 120 Callback0::Type* callback) { |
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
105 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc. | 122 for (size_t i = 0; i < modules.size(); ++i) { |
106 if (PK11_NeedLogin(module->os_module_handle()) && | 123 if (ShouldShowDialog(modules[i].get())) { |
107 !PK11_IsLoggedIn(module->os_module_handle(), NULL /* wincx */)) { | 124 (new SlotUnlocker(modules, reason, host, callback))->Start(); |
108 (new SlotUnlocker(module, reason, host, callback))->Start(); | 125 return; |
wtc
2011/03/02 03:33:28
BUG: this return statement causes us to not unlock
mattm
2011/03/05 02:16:32
The SlotUnlocker will unlock all the slots, this l
| |
109 } else { | 126 } |
110 callback->Run(); | |
111 } | 127 } |
128 callback->Run(); | |
112 } | 129 } |
113 | 130 |
114 void UnlockCertSlotIfNecessary(net::X509Certificate* cert, | 131 void UnlockCertSlotIfNecessary(net::X509Certificate* cert, |
115 browser::CryptoModulePasswordReason reason, | 132 browser::CryptoModulePasswordReason reason, |
116 const std::string& host, | 133 const std::string& host, |
117 Callback0::Type* callback) { | 134 Callback0::Type* callback) { |
118 scoped_refptr<net::CryptoModule> module(net::CryptoModule::CreateFromHandle( | 135 net::CryptoModuleList modules; |
136 modules.push_back(net::CryptoModule::CreateFromHandle( | |
119 cert->os_cert_handle()->slot)); | 137 cert->os_cert_handle()->slot)); |
120 UnlockSlotIfNecessary(module.get(), reason, host, callback); | 138 UnlockSlotsIfNecessary(modules, reason, host, callback); |
121 } | 139 } |
122 | 140 |
123 } // namespace browser | 141 } // namespace browser |
OLD | NEW |