Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chromeos/dbus/session_manager_client.h" | 5 #include "chromeos/dbus/session_manager_client.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <sys/socket.h> | |
| 10 | 9 |
| 11 #include "base/bind.h" | 10 #include "base/bind.h" |
| 12 #include "base/callback.h" | 11 #include "base/callback.h" |
| 13 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 14 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 15 #include "base/location.h" | 14 #include "base/location.h" |
| 16 #include "base/macros.h" | 15 #include "base/macros.h" |
| 17 #include "base/path_service.h" | 16 #include "base/path_service.h" |
| 18 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 19 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 59 // Helper to write a file in a background thread. | 58 // Helper to write a file in a background thread. |
| 60 void StoreFile(const base::FilePath& path, const std::string& data) { | 59 void StoreFile(const base::FilePath& path, const std::string& data) { |
| 61 const int size = static_cast<int>(data.size()); | 60 const int size = static_cast<int>(data.size()); |
| 62 if (path.empty() || | 61 if (path.empty() || |
| 63 !base::CreateDirectory(path.DirName()) || | 62 !base::CreateDirectory(path.DirName()) || |
| 64 base::WriteFile(path, data.data(), size) != size) { | 63 base::WriteFile(path, data.data(), size) != size) { |
| 65 LOG(WARNING) << "Failed to write to " << path.value(); | 64 LOG(WARNING) << "Failed to write to " << path.value(); |
| 66 } | 65 } |
| 67 } | 66 } |
| 68 | 67 |
| 69 // Creates a pair of file descriptors that form a conduit for trustworthy | |
| 70 // transfer of credentials between Chrome and the session_manager | |
| 71 void CreateValidCredConduit(dbus::FileDescriptor* local_auth_fd, | |
| 72 dbus::FileDescriptor* remote_auth_fd) { | |
| 73 int sockets[2] = {-1, -1}; | |
| 74 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { | |
| 75 PLOG(ERROR) << "Failed to create a unix domain socketpair"; | |
| 76 return; | |
| 77 } | |
| 78 | |
| 79 local_auth_fd->PutValue(sockets[0]); | |
| 80 local_auth_fd->CheckValidity(); | |
| 81 | |
| 82 remote_auth_fd->PutValue(sockets[1]); | |
| 83 remote_auth_fd->CheckValidity(); | |
| 84 } | |
| 85 | |
| 86 } // namespace | 68 } // namespace |
| 87 | 69 |
| 88 // The SessionManagerClient implementation used in production. | 70 // The SessionManagerClient implementation used in production. |
| 89 class SessionManagerClientImpl : public SessionManagerClient { | 71 class SessionManagerClientImpl : public SessionManagerClient { |
| 90 public: | 72 public: |
| 91 SessionManagerClientImpl() | 73 SessionManagerClientImpl() |
| 92 : session_manager_proxy_(NULL), | 74 : session_manager_proxy_(NULL), |
| 93 screen_is_locked_(false), | 75 screen_is_locked_(false), |
| 94 weak_ptr_factory_(this) {} | 76 weak_ptr_factory_(this) {} |
| 95 | 77 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 113 } | 95 } |
| 114 | 96 |
| 115 bool IsScreenLocked() const override { return screen_is_locked_; } | 97 bool IsScreenLocked() const override { return screen_is_locked_; } |
| 116 | 98 |
| 117 void EmitLoginPromptVisible() override { | 99 void EmitLoginPromptVisible() override { |
| 118 SimpleMethodCallToSessionManager( | 100 SimpleMethodCallToSessionManager( |
| 119 login_manager::kSessionManagerEmitLoginPromptVisible); | 101 login_manager::kSessionManagerEmitLoginPromptVisible); |
| 120 FOR_EACH_OBSERVER(Observer, observers_, EmitLoginPromptVisibleCalled()); | 102 FOR_EACH_OBSERVER(Observer, observers_, EmitLoginPromptVisibleCalled()); |
| 121 } | 103 } |
| 122 | 104 |
| 123 void RestartJob(const std::vector<std::string>& argv) override { | 105 void RestartJob(int socket_fd, |
| 124 dbus::ScopedFileDescriptor local_auth_fd(new dbus::FileDescriptor); | 106 const std::vector<std::string>& argv, |
| 125 dbus::ScopedFileDescriptor remote_auth_fd(new dbus::FileDescriptor); | 107 const VoidDBusMethodCallback& callback) override { |
| 126 | 108 dbus::MethodCall method_call(login_manager::kSessionManagerInterface, |
| 127 // session_manager's RestartJob call requires the caller to open a socket | 109 login_manager::kSessionManagerRestartJob); |
| 128 // pair and pass one end over dbus while holding the local end open for the | 110 dbus::MessageWriter writer(&method_call); |
| 129 // duration of the call. session_manager uses this to determine whether the | 111 writer.AppendFileDescriptor(socket_fd); |
| 130 // PID the restart request originates from belongs to the browser itself. | 112 writer.AppendArrayOfStrings(argv); |
| 131 // | 113 session_manager_proxy_->CallMethod( |
| 132 // Here, we call CreateValidCredConduit() to create the socket pair, | 114 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 133 // and then pass both ends along to CallRestartJobWithValidFd(), which | 115 base::Bind(&SessionManagerClientImpl::OnRestartJob, |
| 134 // takes care of them from there. | 116 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 135 // NB: PostTaskAndReply ensures that the second callback (which owns the | |
| 136 // ScopedFileDescriptor objects) outlives the first, so passing the | |
| 137 // bare pointers to CreateValidCredConduit is safe... | |
| 138 // -- BUT -- | |
| 139 // you have to grab pointers to the contents of {local,remote}_auth_fd | |
| 140 // _before_ they're acted on by base::Passed() below. Passing ownership | |
| 141 // of the ScopedFileDescriptor objects to the callback actually nulls | |
| 142 // out the storage inside the local instances. Since there are | |
| 143 // no guarantees about the order of evaluation of arguments in a | |
| 144 // function call, merely having them appear earlier among the args | |
| 145 // to PostTaskAndReply() is not enough. Relying on this crashed on | |
| 146 // some platforms. | |
| 147 base::Closure create_credentials_conduit_closure = base::Bind( | |
| 148 &CreateValidCredConduit, local_auth_fd.get(), remote_auth_fd.get()); | |
| 149 | |
| 150 base::WorkerPool::PostTaskAndReply( | |
| 151 FROM_HERE, create_credentials_conduit_closure, | |
|
stevenjb
2016/09/06 15:59:28
It looks like before we were calling socketpair()
| |
| 152 base::Bind(&SessionManagerClientImpl::CallRestartJobWithValidFd, | |
| 153 weak_ptr_factory_.GetWeakPtr(), base::Passed(&local_auth_fd), | |
| 154 base::Passed(&remote_auth_fd), argv), | |
| 155 false); | |
| 156 } | 117 } |
| 157 | 118 |
| 158 void StartSession(const cryptohome::Identification& cryptohome_id) override { | 119 void StartSession(const cryptohome::Identification& cryptohome_id) override { |
| 159 dbus::MethodCall method_call(login_manager::kSessionManagerInterface, | 120 dbus::MethodCall method_call(login_manager::kSessionManagerInterface, |
| 160 login_manager::kSessionManagerStartSession); | 121 login_manager::kSessionManagerStartSession); |
| 161 dbus::MessageWriter writer(&method_call); | 122 dbus::MessageWriter writer(&method_call); |
| 162 writer.AppendString(cryptohome_id.id()); | 123 writer.AppendString(cryptohome_id.id()); |
| 163 writer.AppendString(""); // Unique ID is deprecated | 124 writer.AppendString(""); // Unique ID is deprecated |
| 164 session_manager_proxy_->CallMethod( | 125 session_manager_proxy_->CallMethod( |
| 165 &method_call, | 126 &method_call, |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 484 session_manager_proxy_->CallMethod( | 445 session_manager_proxy_->CallMethod( |
| 485 &method_call, | 446 &method_call, |
| 486 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 447 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 487 base::Bind( | 448 base::Bind( |
| 488 &SessionManagerClientImpl::OnStorePolicy, | 449 &SessionManagerClientImpl::OnStorePolicy, |
| 489 weak_ptr_factory_.GetWeakPtr(), | 450 weak_ptr_factory_.GetWeakPtr(), |
| 490 method_name, | 451 method_name, |
| 491 callback)); | 452 callback)); |
| 492 } | 453 } |
| 493 | 454 |
| 494 // Calls RestartJob to tell the session manager to restart the browser using | |
| 495 // the contents of |argv| as the command line, authorizing the call using | |
| 496 // credentials acquired via |remote_auth_fd|. Ownership of |local_auth_fd| is | |
| 497 // held for the duration of the dbus call. | |
| 498 void CallRestartJobWithValidFd(dbus::ScopedFileDescriptor local_auth_fd, | |
| 499 dbus::ScopedFileDescriptor remote_auth_fd, | |
| 500 const std::vector<std::string>& argv) { | |
| 501 VLOG(1) << "CallRestartJobWithValidFd"; | |
| 502 dbus::MethodCall method_call(login_manager::kSessionManagerInterface, | |
| 503 login_manager::kSessionManagerRestartJob); | |
| 504 dbus::MessageWriter writer(&method_call); | |
| 505 writer.AppendFileDescriptor(*remote_auth_fd); | |
| 506 writer.AppendArrayOfStrings(argv); | |
| 507 | |
| 508 // Ownership of local_auth_fd is passed to the callback that is to be | |
| 509 // called on completion of this method call. This keeps the browser end | |
| 510 // of the socket-pair alive for the duration of the RPC. | |
| 511 session_manager_proxy_->CallMethod( | |
| 512 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
| 513 base::Bind(&SessionManagerClientImpl::OnRestartJob, | |
| 514 weak_ptr_factory_.GetWeakPtr(), | |
| 515 base::Passed(&local_auth_fd))); | |
| 516 } | |
| 517 | |
| 518 // Called when kSessionManagerRestartJob method is complete. | 455 // Called when kSessionManagerRestartJob method is complete. |
| 519 // Now that the call is complete, local_auth_fd can be closed and discarded, | 456 void OnRestartJob(const VoidDBusMethodCallback& callback, |
| 520 // which will happen automatically when it goes out of scope. | |
| 521 void OnRestartJob(dbus::ScopedFileDescriptor local_auth_fd, | |
| 522 dbus::Response* response) { | 457 dbus::Response* response) { |
| 523 VLOG(1) << "OnRestartJob"; | |
| 524 LOG_IF(ERROR, !response) | 458 LOG_IF(ERROR, !response) |
| 525 << "Failed to call " | 459 << "Failed to call " |
| 526 << login_manager::kSessionManagerRestartJob; | 460 << login_manager::kSessionManagerRestartJob; |
| 461 callback.Run(response ? DBUS_METHOD_CALL_SUCCESS | |
| 462 : DBUS_METHOD_CALL_FAILURE); | |
| 527 } | 463 } |
| 528 | 464 |
| 529 // Called when kSessionManagerStartSession method is complete. | 465 // Called when kSessionManagerStartSession method is complete. |
| 530 void OnStartSession(dbus::Response* response) { | 466 void OnStartSession(dbus::Response* response) { |
| 531 LOG_IF(ERROR, !response) | 467 LOG_IF(ERROR, !response) |
| 532 << "Failed to call " | 468 << "Failed to call " |
| 533 << login_manager::kSessionManagerStartSession; | 469 << login_manager::kSessionManagerStartSession; |
| 534 } | 470 } |
| 535 | 471 |
| 536 // Called when kSessionManagerStopSession method is complete. | 472 // Called when kSessionManagerStopSession method is complete. |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 795 observers_.AddObserver(observer); | 731 observers_.AddObserver(observer); |
| 796 } | 732 } |
| 797 void RemoveObserver(Observer* observer) override { | 733 void RemoveObserver(Observer* observer) override { |
| 798 observers_.RemoveObserver(observer); | 734 observers_.RemoveObserver(observer); |
| 799 } | 735 } |
| 800 bool HasObserver(const Observer* observer) const override { | 736 bool HasObserver(const Observer* observer) const override { |
| 801 return observers_.HasObserver(observer); | 737 return observers_.HasObserver(observer); |
| 802 } | 738 } |
| 803 bool IsScreenLocked() const override { return screen_is_locked_; } | 739 bool IsScreenLocked() const override { return screen_is_locked_; } |
| 804 void EmitLoginPromptVisible() override {} | 740 void EmitLoginPromptVisible() override {} |
| 805 void RestartJob(const std::vector<std::string>& argv) override {} | 741 void RestartJob(int socket_fd, |
| 742 const std::vector<std::string>& argv, | |
| 743 const VoidDBusMethodCallback& callback) override {} | |
| 806 void StartSession(const cryptohome::Identification& cryptohome_id) override {} | 744 void StartSession(const cryptohome::Identification& cryptohome_id) override {} |
| 807 void StopSession() override {} | 745 void StopSession() override {} |
| 808 void NotifySupervisedUserCreationStarted() override {} | 746 void NotifySupervisedUserCreationStarted() override {} |
| 809 void NotifySupervisedUserCreationFinished() override {} | 747 void NotifySupervisedUserCreationFinished() override {} |
| 810 void StartDeviceWipe() override {} | 748 void StartDeviceWipe() override {} |
| 811 void RequestLockScreen() override { | 749 void RequestLockScreen() override { |
| 812 if (delegate_) | 750 if (delegate_) |
| 813 delegate_->LockScreenForStub(); | 751 delegate_->LockScreenForStub(); |
| 814 } | 752 } |
| 815 void NotifyLockScreenShown() override { | 753 void NotifyLockScreenShown() override { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 973 | 911 |
| 974 SessionManagerClient* SessionManagerClient::Create( | 912 SessionManagerClient* SessionManagerClient::Create( |
| 975 DBusClientImplementationType type) { | 913 DBusClientImplementationType type) { |
| 976 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) | 914 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) |
| 977 return new SessionManagerClientImpl(); | 915 return new SessionManagerClientImpl(); |
| 978 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); | 916 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); |
| 979 return new SessionManagerClientStubImpl(); | 917 return new SessionManagerClientStubImpl(); |
| 980 } | 918 } |
| 981 | 919 |
| 982 } // namespace chromeos | 920 } // namespace chromeos |
| OLD | NEW |