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
12namespace remoting {
13
14ScopedSd 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.
30std::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.
42ScopedSid 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
68bool 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