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 <memory> | 10 #include <memory> |
12 | 11 |
13 #include "base/bind.h" | 12 #include "base/bind.h" |
14 #include "base/callback.h" | 13 #include "base/callback.h" |
15 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
16 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
17 #include "base/location.h" | 16 #include "base/location.h" |
18 #include "base/macros.h" | 17 #include "base/macros.h" |
19 #include "base/path_service.h" | 18 #include "base/path_service.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 // Helper to write a file in a background thread. | 60 // Helper to write a file in a background thread. |
62 void StoreFile(const base::FilePath& path, const std::string& data) { | 61 void StoreFile(const base::FilePath& path, const std::string& data) { |
63 const int size = static_cast<int>(data.size()); | 62 const int size = static_cast<int>(data.size()); |
64 if (path.empty() || | 63 if (path.empty() || |
65 !base::CreateDirectory(path.DirName()) || | 64 !base::CreateDirectory(path.DirName()) || |
66 base::WriteFile(path, data.data(), size) != size) { | 65 base::WriteFile(path, data.data(), size) != size) { |
67 LOG(WARNING) << "Failed to write to " << path.value(); | 66 LOG(WARNING) << "Failed to write to " << path.value(); |
68 } | 67 } |
69 } | 68 } |
70 | 69 |
71 // Creates a pair of file descriptors that form a conduit for trustworthy | |
72 // transfer of credentials between Chrome and the session_manager | |
73 void CreateValidCredConduit(dbus::FileDescriptor* local_auth_fd, | |
74 dbus::FileDescriptor* remote_auth_fd) { | |
75 int sockets[2] = {-1, -1}; | |
76 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { | |
77 PLOG(ERROR) << "Failed to create a unix domain socketpair"; | |
78 return; | |
79 } | |
80 | |
81 local_auth_fd->PutValue(sockets[0]); | |
82 local_auth_fd->CheckValidity(); | |
83 | |
84 remote_auth_fd->PutValue(sockets[1]); | |
85 remote_auth_fd->CheckValidity(); | |
86 } | |
87 | |
88 } // namespace | 70 } // namespace |
89 | 71 |
90 // The SessionManagerClient implementation used in production. | 72 // The SessionManagerClient implementation used in production. |
91 class SessionManagerClientImpl : public SessionManagerClient { | 73 class SessionManagerClientImpl : public SessionManagerClient { |
92 public: | 74 public: |
93 SessionManagerClientImpl() | 75 SessionManagerClientImpl() |
94 : session_manager_proxy_(NULL), | 76 : session_manager_proxy_(NULL), |
95 screen_is_locked_(false), | 77 screen_is_locked_(false), |
96 weak_ptr_factory_(this) {} | 78 weak_ptr_factory_(this) {} |
97 | 79 |
(...skipping 17 matching lines...) Expand all Loading... |
115 } | 97 } |
116 | 98 |
117 bool IsScreenLocked() const override { return screen_is_locked_; } | 99 bool IsScreenLocked() const override { return screen_is_locked_; } |
118 | 100 |
119 void EmitLoginPromptVisible() override { | 101 void EmitLoginPromptVisible() override { |
120 SimpleMethodCallToSessionManager( | 102 SimpleMethodCallToSessionManager( |
121 login_manager::kSessionManagerEmitLoginPromptVisible); | 103 login_manager::kSessionManagerEmitLoginPromptVisible); |
122 FOR_EACH_OBSERVER(Observer, observers_, EmitLoginPromptVisibleCalled()); | 104 FOR_EACH_OBSERVER(Observer, observers_, EmitLoginPromptVisibleCalled()); |
123 } | 105 } |
124 | 106 |
125 void RestartJob(const std::vector<std::string>& argv) override { | 107 void RestartJob(int socket_fd, |
126 dbus::ScopedFileDescriptor local_auth_fd(new dbus::FileDescriptor); | 108 const std::vector<std::string>& argv, |
127 dbus::ScopedFileDescriptor remote_auth_fd(new dbus::FileDescriptor); | 109 const VoidDBusMethodCallback& callback) override { |
128 | 110 dbus::MethodCall method_call(login_manager::kSessionManagerInterface, |
129 // session_manager's RestartJob call requires the caller to open a socket | 111 login_manager::kSessionManagerRestartJob); |
130 // pair and pass one end over dbus while holding the local end open for the | 112 dbus::MessageWriter writer(&method_call); |
131 // duration of the call. session_manager uses this to determine whether the | 113 writer.AppendFileDescriptor(socket_fd); |
132 // PID the restart request originates from belongs to the browser itself. | 114 writer.AppendArrayOfStrings(argv); |
133 // | 115 session_manager_proxy_->CallMethod( |
134 // Here, we call CreateValidCredConduit() to create the socket pair, | 116 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
135 // and then pass both ends along to CallRestartJobWithValidFd(), which | 117 base::Bind(&SessionManagerClientImpl::OnRestartJob, |
136 // takes care of them from there. | 118 weak_ptr_factory_.GetWeakPtr(), callback)); |
137 // NB: PostTaskAndReply ensures that the second callback (which owns the | |
138 // ScopedFileDescriptor objects) outlives the first, so passing the | |
139 // bare pointers to CreateValidCredConduit is safe... | |
140 // -- BUT -- | |
141 // you have to grab pointers to the contents of {local,remote}_auth_fd | |
142 // _before_ they're acted on by base::Passed() below. Passing ownership | |
143 // of the ScopedFileDescriptor objects to the callback actually nulls | |
144 // out the storage inside the local instances. Since there are | |
145 // no guarantees about the order of evaluation of arguments in a | |
146 // function call, merely having them appear earlier among the args | |
147 // to PostTaskAndReply() is not enough. Relying on this crashed on | |
148 // some platforms. | |
149 base::Closure create_credentials_conduit_closure = base::Bind( | |
150 &CreateValidCredConduit, local_auth_fd.get(), remote_auth_fd.get()); | |
151 | |
152 base::WorkerPool::PostTaskAndReply( | |
153 FROM_HERE, create_credentials_conduit_closure, | |
154 base::Bind(&SessionManagerClientImpl::CallRestartJobWithValidFd, | |
155 weak_ptr_factory_.GetWeakPtr(), base::Passed(&local_auth_fd), | |
156 base::Passed(&remote_auth_fd), argv), | |
157 false); | |
158 } | 119 } |
159 | 120 |
160 void StartSession(const cryptohome::Identification& cryptohome_id) override { | 121 void StartSession(const cryptohome::Identification& cryptohome_id) override { |
161 dbus::MethodCall method_call(login_manager::kSessionManagerInterface, | 122 dbus::MethodCall method_call(login_manager::kSessionManagerInterface, |
162 login_manager::kSessionManagerStartSession); | 123 login_manager::kSessionManagerStartSession); |
163 dbus::MessageWriter writer(&method_call); | 124 dbus::MessageWriter writer(&method_call); |
164 writer.AppendString(cryptohome_id.id()); | 125 writer.AppendString(cryptohome_id.id()); |
165 writer.AppendString(""); // Unique ID is deprecated | 126 writer.AppendString(""); // Unique ID is deprecated |
166 session_manager_proxy_->CallMethod( | 127 session_manager_proxy_->CallMethod( |
167 &method_call, | 128 &method_call, |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 session_manager_proxy_->CallMethod( | 459 session_manager_proxy_->CallMethod( |
499 &method_call, | 460 &method_call, |
500 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 461 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
501 base::Bind( | 462 base::Bind( |
502 &SessionManagerClientImpl::OnStorePolicy, | 463 &SessionManagerClientImpl::OnStorePolicy, |
503 weak_ptr_factory_.GetWeakPtr(), | 464 weak_ptr_factory_.GetWeakPtr(), |
504 method_name, | 465 method_name, |
505 callback)); | 466 callback)); |
506 } | 467 } |
507 | 468 |
508 // Calls RestartJob to tell the session manager to restart the browser using | |
509 // the contents of |argv| as the command line, authorizing the call using | |
510 // credentials acquired via |remote_auth_fd|. Ownership of |local_auth_fd| is | |
511 // held for the duration of the dbus call. | |
512 void CallRestartJobWithValidFd(dbus::ScopedFileDescriptor local_auth_fd, | |
513 dbus::ScopedFileDescriptor remote_auth_fd, | |
514 const std::vector<std::string>& argv) { | |
515 VLOG(1) << "CallRestartJobWithValidFd"; | |
516 dbus::MethodCall method_call(login_manager::kSessionManagerInterface, | |
517 login_manager::kSessionManagerRestartJob); | |
518 dbus::MessageWriter writer(&method_call); | |
519 writer.AppendFileDescriptor(*remote_auth_fd); | |
520 writer.AppendArrayOfStrings(argv); | |
521 | |
522 // Ownership of local_auth_fd is passed to the callback that is to be | |
523 // called on completion of this method call. This keeps the browser end | |
524 // of the socket-pair alive for the duration of the RPC. | |
525 session_manager_proxy_->CallMethod( | |
526 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
527 base::Bind(&SessionManagerClientImpl::OnRestartJob, | |
528 weak_ptr_factory_.GetWeakPtr(), | |
529 base::Passed(&local_auth_fd))); | |
530 } | |
531 | |
532 // Called when kSessionManagerRestartJob method is complete. | 469 // Called when kSessionManagerRestartJob method is complete. |
533 // Now that the call is complete, local_auth_fd can be closed and discarded, | 470 void OnRestartJob(const VoidDBusMethodCallback& callback, |
534 // which will happen automatically when it goes out of scope. | |
535 void OnRestartJob(dbus::ScopedFileDescriptor local_auth_fd, | |
536 dbus::Response* response) { | 471 dbus::Response* response) { |
537 VLOG(1) << "OnRestartJob"; | |
538 LOG_IF(ERROR, !response) | 472 LOG_IF(ERROR, !response) |
539 << "Failed to call " | 473 << "Failed to call " |
540 << login_manager::kSessionManagerRestartJob; | 474 << login_manager::kSessionManagerRestartJob; |
| 475 callback.Run(response ? DBUS_METHOD_CALL_SUCCESS |
| 476 : DBUS_METHOD_CALL_FAILURE); |
541 } | 477 } |
542 | 478 |
543 // Called when kSessionManagerStartSession method is complete. | 479 // Called when kSessionManagerStartSession method is complete. |
544 void OnStartSession(dbus::Response* response) { | 480 void OnStartSession(dbus::Response* response) { |
545 LOG_IF(ERROR, !response) | 481 LOG_IF(ERROR, !response) |
546 << "Failed to call " | 482 << "Failed to call " |
547 << login_manager::kSessionManagerStartSession; | 483 << login_manager::kSessionManagerStartSession; |
548 } | 484 } |
549 | 485 |
550 // Called when kSessionManagerStopSession method is complete. | 486 // Called when kSessionManagerStopSession method is complete. |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 observers_.AddObserver(observer); | 745 observers_.AddObserver(observer); |
810 } | 746 } |
811 void RemoveObserver(Observer* observer) override { | 747 void RemoveObserver(Observer* observer) override { |
812 observers_.RemoveObserver(observer); | 748 observers_.RemoveObserver(observer); |
813 } | 749 } |
814 bool HasObserver(const Observer* observer) const override { | 750 bool HasObserver(const Observer* observer) const override { |
815 return observers_.HasObserver(observer); | 751 return observers_.HasObserver(observer); |
816 } | 752 } |
817 bool IsScreenLocked() const override { return screen_is_locked_; } | 753 bool IsScreenLocked() const override { return screen_is_locked_; } |
818 void EmitLoginPromptVisible() override {} | 754 void EmitLoginPromptVisible() override {} |
819 void RestartJob(const std::vector<std::string>& argv) override {} | 755 void RestartJob(int socket_fd, |
| 756 const std::vector<std::string>& argv, |
| 757 const VoidDBusMethodCallback& callback) override {} |
820 void StartSession(const cryptohome::Identification& cryptohome_id) override {} | 758 void StartSession(const cryptohome::Identification& cryptohome_id) override {} |
821 void StopSession() override {} | 759 void StopSession() override {} |
822 void NotifySupervisedUserCreationStarted() override {} | 760 void NotifySupervisedUserCreationStarted() override {} |
823 void NotifySupervisedUserCreationFinished() override {} | 761 void NotifySupervisedUserCreationFinished() override {} |
824 void StartDeviceWipe() override {} | 762 void StartDeviceWipe() override {} |
825 void RequestLockScreen() override { | 763 void RequestLockScreen() override { |
826 if (delegate_) | 764 if (delegate_) |
827 delegate_->LockScreenForStub(); | 765 delegate_->LockScreenForStub(); |
828 } | 766 } |
829 void NotifyLockScreenShown() override { | 767 void NotifyLockScreenShown() override { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 | 929 |
992 SessionManagerClient* SessionManagerClient::Create( | 930 SessionManagerClient* SessionManagerClient::Create( |
993 DBusClientImplementationType type) { | 931 DBusClientImplementationType type) { |
994 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) | 932 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) |
995 return new SessionManagerClientImpl(); | 933 return new SessionManagerClientImpl(); |
996 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); | 934 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); |
997 return new SessionManagerClientStubImpl(); | 935 return new SessionManagerClientStubImpl(); |
998 } | 936 } |
999 | 937 |
1000 } // namespace chromeos | 938 } // namespace chromeos |
OLD | NEW |