// Copyright 2016 The Crashpad Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "util/win/registration_protocol_win.h" #include #include #include #include #include #include #include "base/logging.h" #include "base/notreached.h" #include "gtest/gtest.h" #include "test/errors.h" #include "util/win/scoped_handle.h" #include "util/win/scoped_local_alloc.h" namespace crashpad { namespace test { namespace { std::wstring GetStringFromSid(PSID sid) { LPWSTR sid_str; if (!ConvertSidToStringSid(sid, &sid_str)) { PLOG(ERROR) << "ConvertSidToStringSid"; return std::wstring(); } ScopedLocalAlloc sid_str_ptr(sid_str); return sid_str; } std::wstring GetUserSidString() { HANDLE token_handle; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token_handle)) { PLOG(ERROR) << "OpenProcessToken"; return std::wstring(); } ScopedKernelHANDLE token(token_handle); DWORD user_size = 0; GetTokenInformation(token.get(), TokenUser, nullptr, 0, &user_size); if (user_size == 0) { PLOG(ERROR) << "GetTokenInformation Size"; return std::wstring(); } std::vector user(user_size); if (!GetTokenInformation( token.get(), TokenUser, user.data(), user_size, &user_size)) { PLOG(ERROR) << "GetTokenInformation"; return std::wstring(); } TOKEN_USER* user_ptr = reinterpret_cast(user.data()); return GetStringFromSid(user_ptr->User.Sid); } void CheckAce(PACL acl, DWORD index, BYTE check_ace_type, ACCESS_MASK check_mask, const std::wstring& check_sid) { ASSERT_FALSE(check_sid.empty()); void* ace_ptr; ASSERT_TRUE(GetAce(acl, index, &ace_ptr)); ACE_HEADER* header = static_cast(ace_ptr); ASSERT_EQ(check_ace_type, header->AceType); ASSERT_EQ(0, header->AceFlags); PSID sid = nullptr; ACCESS_MASK mask = 0; switch (header->AceType) { case ACCESS_ALLOWED_ACE_TYPE: { ACCESS_ALLOWED_ACE* allowed_ace = static_cast(ace_ptr); sid = &allowed_ace->SidStart; mask = allowed_ace->Mask; } break; case SYSTEM_MANDATORY_LABEL_ACE_TYPE: { SYSTEM_MANDATORY_LABEL_ACE* label_ace = static_cast(ace_ptr); sid = &label_ace->SidStart; mask = label_ace->Mask; } break; default: NOTREACHED(); break; } ASSERT_EQ(check_mask, mask); ASSERT_EQ(check_sid, GetStringFromSid(sid)); } TEST(SecurityDescriptor, NamedPipeDefault) { const void* sec_desc = GetSecurityDescriptorForNamedPipeInstance(nullptr); PACL acl; BOOL acl_present; BOOL acl_defaulted; ASSERT_TRUE(GetSecurityDescriptorDacl( const_cast(sec_desc), &acl_present, &acl, &acl_defaulted)); ASSERT_EQ(3, acl->AceCount); CheckAce(acl, 0, ACCESS_ALLOWED_ACE_TYPE, GENERIC_ALL, GetUserSidString()); // Check SYSTEM user SID. CheckAce(acl, 1, ACCESS_ALLOWED_ACE_TYPE, GENERIC_ALL, L"S-1-5-18"); // Check ALL APPLICATION PACKAGES group SID. CheckAce(acl, 2, ACCESS_ALLOWED_ACE_TYPE, GENERIC_READ | GENERIC_WRITE, L"S-1-15-2-1"); ASSERT_TRUE(GetSecurityDescriptorSacl( const_cast(sec_desc), &acl_present, &acl, &acl_defaulted)); ASSERT_EQ(1, acl->AceCount); CheckAce(acl, 0, SYSTEM_MANDATORY_LABEL_ACE_TYPE, 0, L"S-1-16-0"); } TEST(SecurityDescriptor, MatchesAdvapi32) { // This security descriptor is built manually in the connection code to avoid // calling the advapi32 functions. Verify that it returns the same thing as // ConvertStringSecurityDescriptorToSecurityDescriptor() would. // Mandatory Label, no ACE flags, no ObjectType, integrity level // untrusted. static constexpr wchar_t kSddl[] = L"S:(ML;;;;;S-1-16-0)"; PSECURITY_DESCRIPTOR sec_desc; ULONG sec_desc_len; ASSERT_TRUE(ConvertStringSecurityDescriptorToSecurityDescriptor( kSddl, SDDL_REVISION_1, &sec_desc, &sec_desc_len)) << ErrorMessage("ConvertStringSecurityDescriptorToSecurityDescriptor"); ScopedLocalAlloc sec_desc_owner(sec_desc); size_t created_len; const void* const created = GetFallbackSecurityDescriptorForNamedPipeInstance(&created_len); ASSERT_EQ(created_len, sec_desc_len); EXPECT_EQ(memcmp(sec_desc, created, sec_desc_len), 0); } } // namespace } // namespace test } // namespace crashpad