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 14const wchar_t kSeServiceLogonRight[] = L"SeServiceLogonRight"; 15 16#ifndef STATUS_SUCCESS 17#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 18#endif 19 20namespace { 21 22template<class T> 23class 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 55LocalSecurityPolicy::LocalSecurityPolicy() : policy_(NULL) { 56} 57 58LocalSecurityPolicy::~LocalSecurityPolicy() { 59 Close(); 60} 61 62void LocalSecurityPolicy::Close() { 63 if (policy_) { 64 LsaClose(policy_); 65 policy_ = NULL; 66 } 67} 68 69bool 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 79bool LocalSecurityPolicy::IsPrivilegeSet(const string16& username, 80 const string16& privilage) const { 81 DCHECK(policy_); 82 ATL::CSid user_sid; 83 if (!user_sid.LoadAccount(username.c_str())) { 84 LOG(ERROR) << "Unable to load Sid for" << username; 85 return false; 86 } 87 ScopedLsaMemory<LSA_UNICODE_STRING> rights; 88 ULONG count = 0; 89 NTSTATUS status = ::LsaEnumerateAccountRights( 90 policy_, const_cast<SID*>(user_sid.GetPSID()), rights.Receive(), &count); 91 if (STATUS_SUCCESS != status || !rights.Get()) 92 return false; 93 for (size_t i = 0; i < count; ++i) { 94 if (privilage == rights.Get()[i].Buffer) 95 return true; 96 } 97 return false; 98} 99 100bool LocalSecurityPolicy::SetPrivilege(const string16& username, 101 const string16& privilage) { 102 DCHECK(policy_); 103 ATL::CSid user_sid; 104 if (!user_sid.LoadAccount(username.c_str())) { 105 LOG(ERROR) << "Unable to load Sid for" << username; 106 return false; 107 } 108 LSA_UNICODE_STRING privilege_string; 109 string16 privilage_copy(privilage); 110 privilege_string.Buffer = &privilage_copy[0]; 111 privilege_string.Length = wcslen(privilege_string.Buffer) * 112 sizeof(privilege_string.Buffer[0]); 113 privilege_string.MaximumLength = privilege_string.Length + 114 sizeof(privilege_string.Buffer[0]); 115 return STATUS_SUCCESS == 116 ::LsaAddAccountRights(policy_, const_cast<SID*>(user_sid.GetPSID()), 117 &privilege_string, 1); 118} 119 120