Chromium Code Reviews| 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(const 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(const 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), | |
| 59 reason_(reason), | 57 reason_(reason), |
| 60 server_(server), | 58 server_(server), |
| 61 parent_(parent), | 59 parent_(parent), |
| 62 callback_(callback), | 60 callback_(callback), |
| 63 retry_(PR_FALSE) { | 61 retry_(PR_FALSE) { |
| 64 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 62 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 63 for (const auto& slot : modules) { | |
| 64 modules_.push_back(crypto::ScopedPK11Slot(PK11_ReferenceSlot(slot.get()))); | |
|
mattm
2017/02/24 21:03:39
hm
Bence
2017/02/24 22:43:20
I was also looking at this code. ScopedPK11Slot i
mattm
2017/02/24 22:51:26
Oh, that's actually okay. (I meant to delete that
| |
| 65 } | |
| 65 } | 66 } |
| 66 | 67 |
| 67 void SlotUnlocker::Start() { | 68 void SlotUnlocker::Start() { |
| 68 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 69 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 69 | 70 |
| 70 for (; current_ < modules_.size(); ++current_) { | 71 for (; current_ < modules_.size(); ++current_) { |
| 71 if (ShouldShowDialog(modules_[current_].get())) { | 72 if (ShouldShowDialog(modules_[current_].get())) { |
| 72 ShowCryptoModulePasswordDialog( | 73 ShowCryptoModulePasswordDialog( |
| 73 modules_[current_]->GetTokenName(), | 74 PK11_GetTokenName(modules_[current_].get()), retry_, reason_, |
| 74 retry_, | 75 server_.host(), parent_, |
| 75 reason_, | |
| 76 server_.host(), | |
| 77 parent_, | |
| 78 base::Bind(&SlotUnlocker::GotPassword, base::Unretained(this))); | 76 base::Bind(&SlotUnlocker::GotPassword, base::Unretained(this))); |
| 79 return; | 77 return; |
| 80 } | 78 } |
| 81 } | 79 } |
| 82 Done(); | 80 Done(); |
| 83 } | 81 } |
| 84 | 82 |
| 85 void SlotUnlocker::GotPassword(const std::string& password) { | 83 void SlotUnlocker::GotPassword(const std::string& password) { |
| 86 // TODO(mattm): PK11_DoPassword has something about PK11_Global.verifyPass. | 84 // TODO(mattm): PK11_DoPassword has something about PK11_Global.verifyPass. |
| 87 // Do we need it? | 85 // Do we need it? |
| 88 // http://mxr.mozilla.org/mozilla/source/security/nss/lib/pk11wrap/pk11auth.c# 577 | 86 // http://mxr.mozilla.org/mozilla/source/security/nss/lib/pk11wrap/pk11auth.c# 577 |
| 89 | 87 |
| 90 if (password.empty()) { | 88 if (password.empty()) { |
| 91 // User cancelled entering password. Oh well. | 89 // User cancelled entering password. Oh well. |
| 92 ++current_; | 90 ++current_; |
| 93 Start(); | 91 Start(); |
| 94 return; | 92 return; |
| 95 } | 93 } |
| 96 | 94 |
| 97 // TODO(mattm): handle protectedAuthPath | 95 // TODO(mattm): handle protectedAuthPath |
| 98 SECStatus rv = PK11_CheckUserPassword(modules_[current_]->os_module_handle(), | 96 SECStatus rv = |
| 99 password.c_str()); | 97 PK11_CheckUserPassword(modules_[current_].get(), password.c_str()); |
| 100 if (rv == SECWouldBlock) { | 98 if (rv == SECWouldBlock) { |
| 101 // Incorrect password. Try again. | 99 // Incorrect password. Try again. |
| 102 retry_ = PR_TRUE; | 100 retry_ = PR_TRUE; |
| 103 Start(); | 101 Start(); |
| 104 return; | 102 return; |
| 105 } | 103 } |
| 106 | 104 |
| 107 // TODO(mattm): PK11_DoPassword calls nssTrustDomain_UpdateCachedTokenCerts on | 105 // TODO(mattm): PK11_DoPassword calls nssTrustDomain_UpdateCachedTokenCerts on |
| 108 // non-friendly slots. How important is that? | 106 // non-friendly slots. How important is that? |
| 109 | 107 |
| 110 // Correct password (SECSuccess) or too many attempts/other failure | 108 // Correct password (SECSuccess) or too many attempts/other failure |
| 111 // (SECFailure). Either way we're done with this slot. | 109 // (SECFailure). Either way we're done with this slot. |
| 112 ++current_; | 110 ++current_; |
| 113 Start(); | 111 Start(); |
| 114 } | 112 } |
| 115 | 113 |
| 116 void SlotUnlocker::Done() { | 114 void SlotUnlocker::Done() { |
| 117 DCHECK_EQ(current_, modules_.size()); | 115 DCHECK_EQ(current_, modules_.size()); |
| 118 callback_.Run(); | 116 callback_.Run(); |
| 119 delete this; | 117 delete this; |
| 120 } | 118 } |
| 121 | 119 |
| 122 } // namespace | 120 } // namespace |
| 123 | 121 |
| 124 namespace chrome { | 122 namespace chrome { |
| 125 | 123 |
| 126 void UnlockSlotsIfNecessary(const net::CryptoModuleList& modules, | 124 void UnlockSlotsIfNecessary(const std::vector<crypto::ScopedPK11Slot>& modules, |
| 127 chrome::CryptoModulePasswordReason reason, | 125 chrome::CryptoModulePasswordReason reason, |
| 128 const net::HostPortPair& server, | 126 const net::HostPortPair& server, |
| 129 gfx::NativeWindow parent, | 127 gfx::NativeWindow parent, |
| 130 const base::Closure& callback) { | 128 const base::Closure& callback) { |
| 131 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 129 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 132 for (size_t i = 0; i < modules.size(); ++i) { | 130 for (size_t i = 0; i < modules.size(); ++i) { |
| 133 if (ShouldShowDialog(modules[i].get())) { | 131 if (ShouldShowDialog(modules[i].get())) { |
| 134 (new SlotUnlocker(modules, reason, server, parent, callback))->Start(); | 132 (new SlotUnlocker(modules, reason, server, parent, callback))->Start(); |
| 135 return; | 133 return; |
| 136 } | 134 } |
| 137 } | 135 } |
| 138 callback.Run(); | 136 callback.Run(); |
| 139 } | 137 } |
| 140 | 138 |
| 141 void UnlockCertSlotIfNecessary(net::X509Certificate* cert, | 139 void UnlockCertSlotIfNecessary(net::X509Certificate* cert, |
| 142 chrome::CryptoModulePasswordReason reason, | 140 chrome::CryptoModulePasswordReason reason, |
| 143 const net::HostPortPair& server, | 141 const net::HostPortPair& server, |
| 144 gfx::NativeWindow parent, | 142 gfx::NativeWindow parent, |
| 145 const base::Closure& callback) { | 143 const base::Closure& callback) { |
| 146 net::CryptoModuleList modules; | 144 std::vector<crypto::ScopedPK11Slot> modules; |
| 147 modules.push_back(net::CryptoModule::CreateFromHandle( | 145 modules.push_back( |
| 148 cert->os_cert_handle()->slot)); | 146 crypto::ScopedPK11Slot(PK11_ReferenceSlot(cert->os_cert_handle()->slot))); |
| 149 UnlockSlotsIfNecessary(modules, reason, server, parent, callback); | 147 UnlockSlotsIfNecessary(modules, reason, server, parent, callback); |
| 150 } | 148 } |
| 151 | 149 |
| 152 } // namespace chrome | 150 } // namespace chrome |
| OLD | NEW |