15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "cloud_print/service/win/local_security_policy.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlsecurity.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ntsecapi.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kSeServiceLogonRight[] = L"SeServiceLogonRight";
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef STATUS_SUCCESS
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T>
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedLsaMemory {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedLsaMemory() : lsa_memory_(NULL) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ScopedLsaMemory() {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Close();
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Close() {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (lsa_memory_) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LsaFreeMemory(lsa_memory_);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lsa_memory_ = NULL;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* Get() const {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return lsa_memory_;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T** Receive() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Close();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &lsa_memory_;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* lsa_memory_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedLsaMemory);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LocalSecurityPolicy::LocalSecurityPolicy() : policy_(NULL) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LocalSecurityPolicy::~LocalSecurityPolicy() {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Close();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LocalSecurityPolicy::Close() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (policy_) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LsaClose(policy_);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    policy_ = NULL;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LocalSecurityPolicy::Open() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!policy_);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Close();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LSA_OBJECT_ATTRIBUTES attributes = {0};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return STATUS_SUCCESS ==
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ::LsaOpenPolicy(NULL, &attributes,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      &policy_);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool LocalSecurityPolicy::IsPrivilegeSet(
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& username,
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& privilage) const {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(policy_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ATL::CSid user_sid;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!user_sid.LoadAccount(username.c_str())) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Unable to load Sid for" << username;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedLsaMemory<LSA_UNICODE_STRING> rights;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG count = 0;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS status = ::LsaEnumerateAccountRights(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      policy_, const_cast<SID*>(user_sid.GetPSID()), rights.Receive(), &count);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (STATUS_SUCCESS != status || !rights.Get())
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < count; ++i) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (privilage == rights.Get()[i].Buffer)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool LocalSecurityPolicy::SetPrivilege(const base::string16& username,
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                       const base::string16& privilage) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(policy_);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ATL::CSid user_sid;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!user_sid.LoadAccount(username.c_str())) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Unable to load Sid for" << username;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LSA_UNICODE_STRING privilege_string;
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 privilage_copy(privilage);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  privilege_string.Buffer = &privilage_copy[0];
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  privilege_string.Length = wcslen(privilege_string.Buffer) *
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            sizeof(privilege_string.Buffer[0]);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  privilege_string.MaximumLength = privilege_string.Length +
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   sizeof(privilege_string.Buffer[0]);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return STATUS_SUCCESS ==
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ::LsaAddAccountRights(policy_, const_cast<SID*>(user_sid.GetPSID()),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &privilege_string, 1);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
121