| 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 "remoting/host/win/launch_process_with_token.h" | 5 #include "remoting/host/win/launch_process_with_token.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/win/scoped_handle.h" | 12 #include "base/win/scoped_handle.h" |
| 13 #include "base/win/scoped_process_information.h" | 13 #include "base/win/scoped_process_information.h" |
| 14 #include "base/win/startup_information.h" | |
| 15 | 14 |
| 16 using base::win::ScopedHandle; | 15 using base::win::ScopedHandle; |
| 17 | 16 |
| 18 namespace { | 17 namespace { |
| 19 | 18 |
| 20 // Copies the process token making it a primary impersonation token. | 19 // Copies the process token making it a primary impersonation token. |
| 21 // The returned handle will have |desired_access| rights. | 20 // The returned handle will have |desired_access| rights. |
| 22 bool CopyProcessToken(DWORD desired_access, ScopedHandle* token_out) { | 21 bool CopyProcessToken(DWORD desired_access, ScopedHandle* token_out) { |
| 23 HANDLE temp_handle; | 22 HANDLE temp_handle; |
| 24 if (!OpenProcessToken(GetCurrentProcess(), | 23 if (!OpenProcessToken(GetCurrentProcess(), |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 } | 68 } |
| 70 | 69 |
| 71 *token_out = std::move(privileged_token); | 70 *token_out = std::move(privileged_token); |
| 72 return true; | 71 return true; |
| 73 } | 72 } |
| 74 | 73 |
| 75 } // namespace | 74 } // namespace |
| 76 | 75 |
| 77 namespace remoting { | 76 namespace remoting { |
| 78 | 77 |
| 78 base::LazyInstance<base::Lock>::Leaky g_inherit_handles_lock = |
| 79 LAZY_INSTANCE_INITIALIZER; |
| 80 |
| 79 // Creates a copy of the current process token for the given |session_id| so | 81 // Creates a copy of the current process token for the given |session_id| so |
| 80 // it can be used to launch a process in that session. | 82 // it can be used to launch a process in that session. |
| 81 bool CreateSessionToken(uint32_t session_id, ScopedHandle* token_out) { | 83 bool CreateSessionToken(uint32_t session_id, ScopedHandle* token_out) { |
| 82 ScopedHandle session_token; | 84 ScopedHandle session_token; |
| 83 DWORD desired_access = TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | | 85 DWORD desired_access = TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | |
| 84 TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY; | 86 TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY; |
| 85 if (!CopyProcessToken(desired_access, &session_token)) { | 87 if (!CopyProcessToken(desired_access, &session_token)) { |
| 86 return false; | 88 return false; |
| 87 } | 89 } |
| 88 | 90 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 110 return false; | 112 return false; |
| 111 } | 113 } |
| 112 | 114 |
| 113 // Revert to the default token. | 115 // Revert to the default token. |
| 114 CHECK(RevertToSelf()); | 116 CHECK(RevertToSelf()); |
| 115 | 117 |
| 116 *token_out = std::move(session_token); | 118 *token_out = std::move(session_token); |
| 117 return true; | 119 return true; |
| 118 } | 120 } |
| 119 | 121 |
| 120 bool LaunchProcessWithToken( | 122 bool LaunchProcessWithToken(const base::FilePath& binary, |
| 121 const base::FilePath& binary, | 123 const base::CommandLine::StringType& command_line, |
| 122 const base::CommandLine::StringType& command_line, | 124 HANDLE user_token, |
| 123 HANDLE user_token, | 125 SECURITY_ATTRIBUTES* process_attributes, |
| 124 SECURITY_ATTRIBUTES* process_attributes, | 126 SECURITY_ATTRIBUTES* thread_attributes, |
| 125 SECURITY_ATTRIBUTES* thread_attributes, | 127 bool inherit_handles, |
| 126 const base::HandlesToInheritVector& handles_to_inherit, | 128 DWORD creation_flags, |
| 127 DWORD creation_flags, | 129 const base::char16* desktop_name, |
| 128 const base::char16* desktop_name, | 130 ScopedHandle* process_out, |
| 129 ScopedHandle* process_out, | 131 ScopedHandle* thread_out) { |
| 130 ScopedHandle* thread_out) { | |
| 131 base::FilePath::StringType application_name = binary.value(); | 132 base::FilePath::StringType application_name = binary.value(); |
| 132 | 133 |
| 133 base::win::StartupInformation startup_info_wrapper; | 134 STARTUPINFOW startup_info; |
| 134 STARTUPINFO* startup_info = startup_info_wrapper.startup_info(); | 135 memset(&startup_info, 0, sizeof(startup_info)); |
| 136 startup_info.cb = sizeof(startup_info); |
| 135 if (desktop_name) | 137 if (desktop_name) |
| 136 startup_info->lpDesktop = const_cast<base::char16*>(desktop_name); | 138 startup_info.lpDesktop = const_cast<base::char16*>(desktop_name); |
| 137 | 139 |
| 138 bool inherit_handles = false; | |
| 139 if (!handles_to_inherit.empty()) { | |
| 140 if (handles_to_inherit.size() > | |
| 141 std::numeric_limits<DWORD>::max() / sizeof(HANDLE)) { | |
| 142 DLOG(ERROR) << "Too many handles to inherit."; | |
| 143 return false; | |
| 144 } | |
| 145 | |
| 146 // Ensure the handles can be inherited. | |
| 147 for (HANDLE handle : handles_to_inherit) { | |
| 148 BOOL result = SetHandleInformation(handle, HANDLE_FLAG_INHERIT, | |
| 149 HANDLE_FLAG_INHERIT); | |
| 150 PCHECK(result); | |
| 151 } | |
| 152 | |
| 153 if (!startup_info_wrapper.InitializeProcThreadAttributeList( | |
| 154 /* attribute_count= */ 1)) { | |
| 155 PLOG(ERROR) << "InitializeProcThreadAttributeList()"; | |
| 156 return false; | |
| 157 } | |
| 158 | |
| 159 if (!startup_info_wrapper.UpdateProcThreadAttribute( | |
| 160 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, | |
| 161 const_cast<HANDLE*>(&handles_to_inherit.at(0)), | |
| 162 static_cast<DWORD>(handles_to_inherit.size() * sizeof(HANDLE)))) { | |
| 163 PLOG(ERROR) << "UpdateProcThreadAttribute()"; | |
| 164 return false; | |
| 165 } | |
| 166 | |
| 167 inherit_handles = true; | |
| 168 creation_flags |= EXTENDED_STARTUPINFO_PRESENT; | |
| 169 } | |
| 170 PROCESS_INFORMATION temp_process_info = {}; | 140 PROCESS_INFORMATION temp_process_info = {}; |
| 171 BOOL result = CreateProcessAsUser(user_token, application_name.c_str(), | 141 BOOL result = CreateProcessAsUser(user_token, |
| 142 application_name.c_str(), |
| 172 const_cast<LPWSTR>(command_line.c_str()), | 143 const_cast<LPWSTR>(command_line.c_str()), |
| 173 process_attributes, thread_attributes, | 144 process_attributes, |
| 174 inherit_handles, creation_flags, nullptr, | 145 thread_attributes, |
| 175 nullptr, startup_info, &temp_process_info); | 146 inherit_handles, |
| 147 creation_flags, |
| 148 nullptr, |
| 149 nullptr, |
| 150 &startup_info, |
| 151 &temp_process_info); |
| 176 | 152 |
| 177 if (!result) { | 153 if (!result) { |
| 178 PLOG(ERROR) << "Failed to launch a process with a user token"; | 154 PLOG(ERROR) << "Failed to launch a process with a user token"; |
| 179 return false; | 155 return false; |
| 180 } | 156 } |
| 181 | 157 |
| 182 base::win::ScopedProcessInformation process_info(temp_process_info); | 158 base::win::ScopedProcessInformation process_info(temp_process_info); |
| 183 | 159 |
| 184 CHECK(process_info.IsValid()); | 160 CHECK(process_info.IsValid()); |
| 185 process_out->Set(process_info.TakeProcessHandle()); | 161 process_out->Set(process_info.TakeProcessHandle()); |
| 186 thread_out->Set(process_info.TakeThreadHandle()); | 162 thread_out->Set(process_info.TakeThreadHandle()); |
| 187 return true; | 163 return true; |
| 188 } | 164 } |
| 189 | 165 |
| 190 } // namespace remoting | 166 } // namespace remoting |
| OLD | NEW |