Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: cloud_print/service/win/cloud_print_service.cc

Issue 10824294: Changed Windows account to run service. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "cloud_print/service/win/cloud_print_service.h" 5 #include "cloud_print/service/win/cloud_print_service.h"
6 6
7 #include <atlsecurity.h> 7 #include <atlsecurity.h>
8 #include <iomanip> 8 #include <iomanip>
9 #include <iostream> 9 #include <iostream>
10 10
11 #include "base/at_exit.h" 11 #include "base/at_exit.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/file_path.h" 13 #include "base/file_path.h"
14 #include "base/file_util.h" 14 #include "base/file_util.h"
15 #include "base/path_service.h" 15 #include "base/path_service.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/win/scoped_handle.h" 17 #include "base/win/scoped_handle.h"
18 #include "chrome/installer/launcher_support/chrome_launcher_support.h" 18 #include "chrome/installer/launcher_support/chrome_launcher_support.h"
19 #include "cloud_print/service/service_state.h" 19 #include "cloud_print/service/service_state.h"
20 #include "cloud_print/service/service_switches.h" 20 #include "cloud_print/service/service_switches.h"
21 #include "cloud_print/service/win/chrome_launcher.h" 21 #include "cloud_print/service/win/chrome_launcher.h"
22 #include "cloud_print/service/win/local_security_policy.h"
22 #include "cloud_print/service/win/resource.h" 23 #include "cloud_print/service/win/resource.h"
23 24
24 namespace { 25 namespace {
25 26
26 const wchar_t kServiceStateFileName[] = L"Service State"; 27 const wchar_t kServiceStateFileName[] = L"Service State";
27 28
28 const wchar_t kUserToRunService[] = L"NT AUTHORITY\\LocalService"; 29 const wchar_t kUserToRunService[] = L"NT AUTHORITY\\SYSTEM";
Albert Bodenhamer 2012/08/14 20:38:18 I'm a bit nervous running as SYSTEM by default. A
Vitaly Buka (NO REVIEWS) 2012/08/14 20:58:51 For current user we need to ask password. Probably
Vitaly Buka (NO REVIEWS) 2012/08/14 21:51:00 Removed default user. On 2012/08/14 20:58:51, Vit
29 30
30 // The traits class for Windows Service. 31 // The traits class for Windows Service.
31 class ServiceHandleTraits { 32 class ServiceHandleTraits {
32 public: 33 public:
33 typedef SC_HANDLE Handle; 34 typedef SC_HANDLE Handle;
34 35
35 // Closes the handle. 36 // Closes the handle.
36 static bool CloseHandle(Handle handle) { 37 static bool CloseHandle(Handle handle) {
37 return ::CloseServiceHandle(handle) != FALSE; 38 return ::CloseServiceHandle(handle) != FALSE;
38 } 39 }
(...skipping 25 matching lines...) Expand all
64 FilePath service_path; 65 FilePath service_path;
65 CHECK(PathService::Get(base::FILE_EXE, &service_path)); 66 CHECK(PathService::Get(base::FILE_EXE, &service_path));
66 67
67 std::cout << "Usage: "; 68 std::cout << "Usage: ";
68 std::cout << service_path.BaseName().value(); 69 std::cout << service_path.BaseName().value();
69 std::cout << " ["; 70 std::cout << " [";
70 std::cout << "["; 71 std::cout << "[";
71 std::cout << "["; 72 std::cout << "[";
72 std::cout << " -" << kInstallSwitch; 73 std::cout << " -" << kInstallSwitch;
73 std::cout << " -" << kUserDataDirSwitch << "=DIRECTORY"; 74 std::cout << " -" << kUserDataDirSwitch << "=DIRECTORY";
75 std::cout << "[";
76 std::cout << " -" << kRunAsUser << "=USERNAME";
77 std::cout << " -" << kRunAsPassword << "=PASSWORD";
78 std::cout << "]";
74 std::cout << " [ -" << kQuietSwitch << " ]"; 79 std::cout << " [ -" << kQuietSwitch << " ]";
75 std::cout << "]"; 80 std::cout << "]";
76 std::cout << "]"; 81 std::cout << "]";
77 std::cout << " | -" << kUninstallSwitch; 82 std::cout << " | -" << kUninstallSwitch;
78 std::cout << " | -" << kStartSwitch; 83 std::cout << " | -" << kStartSwitch;
79 std::cout << " | -" << kStopSwitch; 84 std::cout << " | -" << kStopSwitch;
80 std::cout << " ]\n"; 85 std::cout << " ]\n";
81 std::cout << "Manages cloud print windows service.\n\n"; 86 std::cout << "Manages cloud print windows service.\n\n";
82 87
83 static const struct { 88 static const struct {
84 const char* name; 89 const char* name;
85 const char* description; 90 const char* description;
86 } kSwitchHelp[] = { 91 } kSwitchHelp[] = {
87 { kInstallSwitch, "Installs cloud print as service." }, 92 { kInstallSwitch, "Installs cloud print as service." },
88 { kUserDataDirSwitch, "User data directory with \"Service State\" file." }, 93 { kUserDataDirSwitch, "User data directory with \"Service State\" file." },
89 { kQuietSwitch, "Fails without questions if something wrong." }, 94 { kQuietSwitch, "Fails without questions if something wrong." },
90 { kUninstallSwitch, "Uninstalls service." }, 95 { kUninstallSwitch, "Uninstalls service." },
91 { kStartSwitch, "Starts service. May be combined with installation." }, 96 { kStartSwitch, "Starts service. May be combined with installation." },
92 { kStopSwitch, "Stops service." }, 97 { kStopSwitch, "Stops service." },
98 { kRunAsUser, "Windows user to run the service in form DOMAIN\USERNAME. "
99 "Default is LocalSystem. Current User is recommended." },
100 { kRunAsPassword, "Password for windows user to run the service" },
93 }; 101 };
94 102
95 for (size_t i = 0; i < arraysize(kSwitchHelp); ++i) { 103 for (size_t i = 0; i < arraysize(kSwitchHelp); ++i) {
96 std::cout << std::setiosflags(std::ios::left); 104 std::cout << std::setiosflags(std::ios::left);
97 std::cout << " -" << std::setw(15) << kSwitchHelp[i].name; 105 std::cout << " -" << std::setw(15) << kSwitchHelp[i].name;
98 std::cout << kSwitchHelp[i].description << "\n"; 106 std::cout << kSwitchHelp[i].description << "\n";
99 } 107 }
100 std::cout << "\n"; 108 std::cout << "\n";
101 } 109 }
102 110
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 183
176 DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLOUDPRINTSERVICE, 184 DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLOUDPRINTSERVICE,
177 "{8013FB7C-2E3E-4992-B8BD-05C0C4AB0627}") 185 "{8013FB7C-2E3E-4992-B8BD-05C0C4AB0627}")
178 186
179 HRESULT InitializeSecurity() { 187 HRESULT InitializeSecurity() {
180 // TODO(gene): Check if we need to call CoInitializeSecurity and provide 188 // TODO(gene): Check if we need to call CoInitializeSecurity and provide
181 // the appropriate security settings for service. 189 // the appropriate security settings for service.
182 return S_OK; 190 return S_OK;
183 } 191 }
184 192
185 HRESULT InstallService() { 193 HRESULT InstallService(const wchar_t* user, const wchar_t* password) {
186 using namespace chrome_launcher_support; 194 using namespace chrome_launcher_support;
187 195
188 // TODO(vitalybuka): consider "lite" version if we don't want unregister 196 // TODO(vitalybuka): consider "lite" version if we don't want unregister
189 // printers here. 197 // printers here.
190 HRESULT hr = UninstallService(); 198 HRESULT hr = UninstallService();
191 if (FAILED(hr)) 199 if (FAILED(hr))
192 return hr; 200 return hr;
193 201
194 if (GetChromePathForInstallationLevel(SYSTEM_LEVEL_INSTALLATION).empty()) { 202 if (GetChromePathForInstallationLevel(SYSTEM_LEVEL_INSTALLATION).empty()) {
195 LOG(ERROR) << "Found no Chrome installed for all users."; 203 LOG(WARNING) << "Found no Chrome installed for all users.";
196 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
197 } 204 }
198 205
199 hr = UpdateRegistryAppId(true); 206 hr = UpdateRegistryAppId(true);
200 if (FAILED(hr)) 207 if (FAILED(hr))
201 return hr; 208 return hr;
202 209
203 FilePath service_path; 210 FilePath service_path;
204 CHECK(PathService::Get(base::FILE_EXE, &service_path)); 211 CHECK(PathService::Get(base::FILE_EXE, &service_path));
205 CommandLine command_line(service_path); 212 CommandLine command_line(service_path);
206 command_line.AppendSwitch(kServiceSwitch); 213 command_line.AppendSwitch(kServiceSwitch);
207 command_line.AppendSwitchPath(kUserDataDirSwitch, user_data_dir_); 214 command_line.AppendSwitchPath(kUserDataDirSwitch, user_data_dir_);
208 215
216 LocalSecurityPolicy local_security_policy;
217 if (local_security_policy.Open()) {
218 if (!local_security_policy.IsPrivilegeSet(user, kSeServiceLogonRight)) {
219 LOG(WARNING) << "Setting " << kSeServiceLogonRight << " for " << user;
220 if (!local_security_policy.SetPrivilege(user, kSeServiceLogonRight)) {
221 LOG(ERROR) << "Failed to set" << kSeServiceLogonRight;
222 LOG(ERROR) << "Make sure you can run the service with this user.";
223 }
224 }
225 } else {
226 LOG(ERROR) << "Failed to open security policy.";
227 }
228
209 ServiceHandle scm; 229 ServiceHandle scm;
210 hr = OpenServiceManager(&scm); 230 hr = OpenServiceManager(&scm);
211 if (FAILED(hr)) 231 if (FAILED(hr))
212 return hr; 232 return hr;
213 233
214 ServiceHandle service( 234 ServiceHandle service(
215 ::CreateService( 235 ::CreateService(
216 scm, m_szServiceName, m_szServiceName, SERVICE_ALL_ACCESS, 236 scm, m_szServiceName, m_szServiceName, SERVICE_ALL_ACCESS,
217 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, 237 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
218 command_line.GetCommandLineString().c_str(), NULL, NULL, NULL, 238 command_line.GetCommandLineString().c_str(), NULL, NULL, NULL,
219 kUserToRunService, NULL)); 239 user, password));
220 240
221 if (!service.IsValid()) 241 if (!service.IsValid())
222 return HResultFromLastError(); 242 return HResultFromLastError();
223 243
224 return S_OK; 244 return S_OK;
225 } 245 }
226 246
227 HRESULT UninstallService() { 247 HRESULT UninstallService() {
228 if (!Uninstall()) 248 if (!Uninstall())
229 return E_FAIL; 249 return E_FAIL;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 295
276 if (command_line.HasSwitch(kUninstallSwitch)) 296 if (command_line.HasSwitch(kUninstallSwitch))
277 return UninstallService(); 297 return UninstallService();
278 298
279 if (command_line.HasSwitch(kInstallSwitch)) { 299 if (command_line.HasSwitch(kInstallSwitch)) {
280 if (!command_line.HasSwitch(kUserDataDirSwitch)) { 300 if (!command_line.HasSwitch(kUserDataDirSwitch)) {
281 InvalidUsage(); 301 InvalidUsage();
282 return S_FALSE; 302 return S_FALSE;
283 } 303 }
284 304
285 HRESULT hr = ValidateUserDataDir(); 305 CommandLine::StringType run_as_user =
286 if (FAILED(hr)) 306 command_line.GetSwitchValueNative(kRunAsUser);
287 return hr; 307 CommandLine::StringType run_as_password =
308 command_line.GetSwitchValueNative(kRunAsPassword);
309 if (run_as_user.empty())
310 run_as_user = kUserToRunService;
311
312 HRESULT hr = ValidateUserDataDir(run_as_user.c_str());
288 313
289 hr = ProcessServiceState(command_line.HasSwitch(kQuietSwitch)); 314 hr = ProcessServiceState(command_line.HasSwitch(kQuietSwitch));
290 if (FAILED(hr)) 315 if (FAILED(hr))
291 return hr; 316 return hr;
292 317
293 hr = InstallService(); 318 hr = InstallService(run_as_user.c_str(), run_as_password.c_str());
294 if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch)) 319 if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch))
295 return StartService(); 320 return StartService();
296 321
297 return hr; 322 return hr;
298 } 323 }
299 324
300 if (command_line.HasSwitch(kStartSwitch)) 325 if (command_line.HasSwitch(kStartSwitch))
301 return StartService(); 326 return StartService();
302 327
303 if (command_line.HasSwitch(kServiceSwitch)) { 328 if (command_line.HasSwitch(kServiceSwitch)) {
304 *is_service = true; 329 *is_service = true;
305 return S_OK; 330 return S_OK;
306 } 331 }
307 332
308 if (command_line.HasSwitch(kConsoleSwitch)) { 333 if (command_line.HasSwitch(kConsoleSwitch)) {
309 ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE); 334 ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE);
310 HRESULT hr = Run(); 335 HRESULT hr = Run();
311 ::SetConsoleCtrlHandler(NULL, FALSE); 336 ::SetConsoleCtrlHandler(NULL, FALSE);
312 return hr; 337 return hr;
313 } 338 }
314 339
315 InvalidUsage(); 340 InvalidUsage();
316 return S_FALSE; 341 return S_FALSE;
317 } 342 }
318 343
319 HRESULT ValidateUserDataDir() { 344 HRESULT ValidateUserDataDir(const wchar_t* user) {
320 FilePath temp_file; 345 FilePath temp_file;
321 const char some_data[] = "1234"; 346 const char some_data[] = "1234";
322 if (!file_util::CreateTemporaryFileInDir(user_data_dir_, &temp_file)) 347 if (!file_util::CreateTemporaryFileInDir(user_data_dir_, &temp_file))
323 return E_FAIL; 348 return E_FAIL;
324 HRESULT hr = WriteFileAsUser(temp_file, kUserToRunService, some_data, 349 HRESULT hr = WriteFileAsUser(temp_file, user, some_data,
325 sizeof(some_data)); 350 sizeof(some_data));
326 if (FAILED(hr)) { 351 if (FAILED(hr)) {
327 LOG(ERROR) << "Failed to write user data. Make sure that account \'" << 352 LOG(ERROR) << "Failed to write user data. Make sure that account \'" <<
328 kUserToRunService << "\'has full access to \'" << 353 user << "\' has full access to \'" <<
329 user_data_dir_.value() << "\'."; 354 user_data_dir_.value() << "\'.";
330 } 355 }
331 file_util::Delete(temp_file, false); 356 file_util::Delete(temp_file, false);
332 return hr; 357 return hr;
333 } 358 }
334 359
335 HRESULT ProcessServiceState(bool quiet) { 360 HRESULT ProcessServiceState(bool quiet) {
336 FilePath file = user_data_dir_.Append(kServiceStateFileName); 361 FilePath file = user_data_dir_.Append(kServiceStateFileName);
337 362
338 for (;;) { 363 for (;;) {
339 std::string contents; 364 std::string contents;
340 ServiceState service_state; 365 ServiceState service_state;
341 366
342 bool is_valid = file_util::ReadFileToString(file, &contents) && 367 bool is_valid = file_util::ReadFileToString(file, &contents) &&
343 service_state.FromString(contents); 368 service_state.FromString(contents);
344 369
345 if (!quiet) { 370 if (!quiet) {
371 std::cout << "\n";
346 std::cout << file.value() << ":\n"; 372 std::cout << file.value() << ":\n";
347 std::cout << contents << "\n"; 373 std::cout << contents << "\n";
348 } 374 }
349 375
350 if (!is_valid) 376 if (!is_valid)
351 LOG(ERROR) << "Invalid file: " << file.value(); 377 LOG(ERROR) << "Invalid file: " << file.value();
352 378
353 if (quiet) 379 if (quiet)
354 return is_valid ? S_OK : HRESULT_FROM_WIN32(ERROR_FILE_INVALID); 380 return is_valid ? S_OK : HRESULT_FROM_WIN32(ERROR_FILE_INVALID);
355 381
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 485
460 BOOL CloudPrintServiceModule::ConsoleCtrlHandler(DWORD type) { 486 BOOL CloudPrintServiceModule::ConsoleCtrlHandler(DWORD type) {
461 PostThreadMessage(_AtlModule.m_dwThreadID, WM_QUIT, 0, 0); 487 PostThreadMessage(_AtlModule.m_dwThreadID, WM_QUIT, 0, 0);
462 return TRUE; 488 return TRUE;
463 } 489 }
464 490
465 int main() { 491 int main() {
466 base::AtExitManager at_exit; 492 base::AtExitManager at_exit;
467 return _AtlModule.WinMain(0); 493 return _AtlModule.WinMain(0);
468 } 494 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698