Home | History | Annotate | Download | only in win
      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