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.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 |