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 |