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