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 "remoting/host/win/security_descriptor.h"
      6 
      7 #include <sddl.h>
      8 
      9 #include "base/strings/string16.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 
     12 namespace remoting {
     13 
     14 ScopedSd ConvertSddlToSd(const std::string& sddl) {
     15   PSECURITY_DESCRIPTOR raw_sd = NULL;
     16   ULONG length = 0;
     17   if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
     18           base::UTF8ToUTF16(sddl).c_str(), SDDL_REVISION_1, &raw_sd, &length)) {
     19     return ScopedSd();
     20   }
     21 
     22   ScopedSd sd(length);
     23   memcpy(sd.get(), raw_sd, length);
     24 
     25   LocalFree(raw_sd);
     26   return sd.Pass();
     27 }
     28 
     29 // Converts a SID into a text string.
     30 std::string ConvertSidToString(SID* sid) {
     31   base::char16* c_sid_string = NULL;
     32   if (!ConvertSidToStringSid(sid, &c_sid_string))
     33     return std::string();
     34 
     35   base::string16 sid_string(c_sid_string);
     36   LocalFree(c_sid_string);
     37   return base::UTF16ToUTF8(sid_string);
     38 }
     39 
     40 // Returns the logon SID of a token. Returns NULL if the token does not specify
     41 // a logon SID or in case of an error.
     42 ScopedSid GetLogonSid(HANDLE token) {
     43   DWORD length = 0;
     44   if (GetTokenInformation(token, TokenGroups, NULL, 0, &length) ||
     45       GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
     46     return ScopedSid();
     47   }
     48 
     49   TypedBuffer<TOKEN_GROUPS> groups(length);
     50   if (!GetTokenInformation(token, TokenGroups, groups.get(), length, &length))
     51     return ScopedSid();
     52 
     53   for (uint32 i = 0; i < groups->GroupCount; ++i) {
     54     if ((groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) ==
     55         SE_GROUP_LOGON_ID) {
     56       length = GetLengthSid(groups->Groups[i].Sid);
     57       ScopedSid logon_sid(length);
     58       if (!CopySid(length, logon_sid.get(), groups->Groups[i].Sid))
     59         return ScopedSid();
     60 
     61       return logon_sid.Pass();
     62     }
     63   }
     64 
     65   return ScopedSid();
     66 }
     67 
     68 bool MakeScopedAbsoluteSd(const ScopedSd& relative_sd,
     69                           ScopedSd* absolute_sd,
     70                           ScopedAcl* dacl,
     71                           ScopedSid* group,
     72                           ScopedSid* owner,
     73                           ScopedAcl* sacl) {
     74   // Get buffer sizes.
     75   DWORD absolute_sd_size = 0;
     76   DWORD dacl_size = 0;
     77   DWORD group_size = 0;
     78   DWORD owner_size = 0;
     79   DWORD sacl_size = 0;
     80   if (MakeAbsoluteSD(relative_sd.get(),
     81                      NULL,
     82                      &absolute_sd_size,
     83                      NULL,
     84                      &dacl_size,
     85                      NULL,
     86                      &sacl_size,
     87                      NULL,
     88                      &owner_size,
     89                      NULL,
     90                      &group_size) ||
     91       GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
     92     return false;
     93   }
     94 
     95   // Allocate buffers.
     96   ScopedSd local_absolute_sd(absolute_sd_size);
     97   ScopedAcl local_dacl(dacl_size);
     98   ScopedSid local_group(group_size);
     99   ScopedSid local_owner(owner_size);
    100   ScopedAcl local_sacl(sacl_size);
    101 
    102   // Do the conversion.
    103   if (!MakeAbsoluteSD(relative_sd.get(),
    104                       local_absolute_sd.get(),
    105                       &absolute_sd_size,
    106                       local_dacl.get(),
    107                       &dacl_size,
    108                       local_sacl.get(),
    109                       &sacl_size,
    110                       local_owner.get(),
    111                       &owner_size,
    112                       local_group.get(),
    113                       &group_size)) {
    114     return false;
    115   }
    116 
    117   absolute_sd->Swap(local_absolute_sd);
    118   dacl->Swap(local_dacl);
    119   group->Swap(local_group);
    120   owner->Swap(local_owner);
    121   sacl->Swap(local_sacl);
    122   return true;
    123 }
    124 
    125 }  // namespace remoting
    126