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 3 // found in the LICENSE file. 4 5 #include "cloud_print/service/win/local_security_policy.h" 6 7 #include <atlsecurity.h> 8 #include <ntsecapi.h> 9 #include <windows.h> 10 11 #include "base/logging.h" 12 #include "base/strings/string_util.h" 13 14 const wchar_t kSeServiceLogonRight[] = L"SeServiceLogonRight"; 15 16 #ifndef STATUS_SUCCESS 17 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 18 #endif 19 20 namespace { 21 22 template<class T> 23 class ScopedLsaMemory { 24 public: 25 ScopedLsaMemory() : lsa_memory_(NULL) { 26 } 27 28 ~ScopedLsaMemory() { 29 Close(); 30 } 31 32 void Close() { 33 if (lsa_memory_) { 34 LsaFreeMemory(lsa_memory_); 35 lsa_memory_ = NULL; 36 } 37 } 38 39 T* Get() const { 40 return lsa_memory_; 41 } 42 43 T** Receive() { 44 Close(); 45 return &lsa_memory_; 46 } 47 48 private: 49 T* lsa_memory_; 50 DISALLOW_COPY_AND_ASSIGN(ScopedLsaMemory); 51 }; 52 53 } // namespace 54 55 LocalSecurityPolicy::LocalSecurityPolicy() : policy_(NULL) { 56 } 57 58 LocalSecurityPolicy::~LocalSecurityPolicy() { 59 Close(); 60 } 61 62 void LocalSecurityPolicy::Close() { 63 if (policy_) { 64 LsaClose(policy_); 65 policy_ = NULL; 66 } 67 } 68 69 bool LocalSecurityPolicy::Open() { 70 DCHECK(!policy_); 71 Close(); 72 LSA_OBJECT_ATTRIBUTES attributes = {0}; 73 return STATUS_SUCCESS == 74 ::LsaOpenPolicy(NULL, &attributes, 75 POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, 76 &policy_); 77 } 78 79 bool LocalSecurityPolicy::IsPrivilegeSet( 80 const base::string16& username, 81 const base::string16& privilage) const { 82 DCHECK(policy_); 83 ATL::CSid user_sid; 84 if (!user_sid.LoadAccount(username.c_str())) { 85 LOG(ERROR) << "Unable to load Sid for" << username; 86 return false; 87 } 88 ScopedLsaMemory<LSA_UNICODE_STRING> rights; 89 ULONG count = 0; 90 NTSTATUS status = ::LsaEnumerateAccountRights( 91 policy_, const_cast<SID*>(user_sid.GetPSID()), rights.Receive(), &count); 92 if (STATUS_SUCCESS != status || !rights.Get()) 93 return false; 94 for (size_t i = 0; i < count; ++i) { 95 if (privilage == rights.Get()[i].Buffer) 96 return true; 97 } 98 return false; 99 } 100 101 bool LocalSecurityPolicy::SetPrivilege(const base::string16& username, 102 const base::string16& privilage) { 103 DCHECK(policy_); 104 ATL::CSid user_sid; 105 if (!user_sid.LoadAccount(username.c_str())) { 106 LOG(ERROR) << "Unable to load Sid for" << username; 107 return false; 108 } 109 LSA_UNICODE_STRING privilege_string; 110 base::string16 privilage_copy(privilage); 111 privilege_string.Buffer = &privilage_copy[0]; 112 privilege_string.Length = wcslen(privilege_string.Buffer) * 113 sizeof(privilege_string.Buffer[0]); 114 privilege_string.MaximumLength = privilege_string.Length + 115 sizeof(privilege_string.Buffer[0]); 116 return STATUS_SUCCESS == 117 ::LsaAddAccountRights(policy_, const_cast<SID*>(user_sid.GetPSID()), 118 &privilege_string, 1); 119 } 120 121