|
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 "sandbox/win/src/app_container.h" |
|
6 |
|
7 #include <Sddl.h> |
|
8 #include <vector> |
|
9 |
|
10 #include "base/logging.h" |
|
11 #include "base/memory/scoped_ptr.h" |
|
12 #include "base/win/startup_information.h" |
|
13 #include "sandbox/win/src/internal_types.h" |
|
14 |
|
15 namespace { |
|
16 |
|
17 // Converts the passed in sid string to a PSID that must be relased with |
|
18 // LocalFree. |
|
19 PSID ConvertSid(const string16& sid) { |
|
20 PSID local_sid; |
|
21 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) |
|
22 return NULL; |
|
23 return local_sid; |
|
24 } |
|
25 |
|
26 template <typename T> |
|
27 T BindFunction(const char* name) { |
|
28 HMODULE module = GetModuleHandle(sandbox::kKerneldllName); |
|
29 void* function = GetProcAddress(module, name); |
|
30 if (!function) { |
|
31 module = GetModuleHandle(sandbox::kKernelBasedllName); |
|
32 function = GetProcAddress(module, name); |
|
33 } |
|
34 return reinterpret_cast<T>(function); |
|
35 } |
|
36 |
|
37 } // namespace |
|
38 |
|
39 namespace sandbox { |
|
40 |
|
41 AppContainerAttributes::AppContainerAttributes() { |
|
42 memset(&capabilities_, 0, sizeof(capabilities_)); |
|
43 } |
|
44 |
|
45 AppContainerAttributes::~AppContainerAttributes() { |
|
46 for (size_t i = 0; i < attributes_.size(); i++) |
|
47 LocalFree(attributes_[i].Sid); |
|
48 LocalFree(capabilities_.AppContainerSid); |
|
49 } |
|
50 |
|
51 ResultCode AppContainerAttributes::SetAppContainer( |
|
52 const string16& app_container_sid, |
|
53 const std::vector<string16>& capabilities) { |
|
54 DCHECK(!capabilities_.AppContainerSid); |
|
55 DCHECK(attributes_.empty()); |
|
56 capabilities_.AppContainerSid = ConvertSid(app_container_sid); |
|
57 if (!capabilities_.AppContainerSid) |
|
58 return SBOX_ERROR_INVALID_APP_CONTAINER; |
|
59 |
|
60 for (size_t i = 0; i < capabilities.size(); i++) { |
|
61 SID_AND_ATTRIBUTES sid_and_attributes; |
|
62 sid_and_attributes.Sid = ConvertSid(capabilities[i]); |
|
63 if (!sid_and_attributes.Sid) |
|
64 return SBOX_ERROR_INVALID_CAPABILITY; |
|
65 |
|
66 sid_and_attributes.Attributes = SE_GROUP_ENABLED; |
|
67 attributes_.push_back(sid_and_attributes); |
|
68 } |
|
69 |
|
70 if (capabilities.size()) { |
|
71 capabilities_.CapabilityCount = static_cast<DWORD>(capabilities.size()); |
|
72 capabilities_.Capabilities = &attributes_[0]; |
|
73 } |
|
74 return SBOX_ALL_OK; |
|
75 } |
|
76 |
|
77 ResultCode AppContainerAttributes::ShareForStartup( |
|
78 base::win::StartupInformation* startup_information) const { |
|
79 // The only thing we support so far is an AppContainer. |
|
80 if (!capabilities_.AppContainerSid) |
|
81 return SBOX_ERROR_INVALID_APP_CONTAINER; |
|
82 |
|
83 if (!startup_information->UpdateProcThreadAttribute( |
|
84 PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, |
|
85 const_cast<SECURITY_CAPABILITIES*>(&capabilities_), |
|
86 sizeof(capabilities_))) { |
|
87 DPLOG(ERROR) << "Failed UpdateProcThreadAttribute"; |
|
88 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; |
|
89 } |
|
90 return SBOX_ALL_OK; |
|
91 } |
|
92 |
|
93 bool AppContainerAttributes::HasAppContainer() const { |
|
94 return (capabilities_.AppContainerSid != NULL); |
|
95 } |
|
96 |
|
97 ResultCode CreateAppContainer(const string16& sid, const string16& name) { |
|
98 PSID local_sid; |
|
99 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) |
|
100 return SBOX_ERROR_INVALID_APP_CONTAINER; |
|
101 |
|
102 typedef HRESULT (WINAPI* AppContainerRegisterSidPtr)(PSID sid, |
|
103 LPCWSTR moniker, |
|
104 LPCWSTR display_name); |
|
105 static AppContainerRegisterSidPtr AppContainerRegisterSid = NULL; |
|
106 |
|
107 if (!AppContainerRegisterSid) { |
|
108 AppContainerRegisterSid = |
|
109 BindFunction<AppContainerRegisterSidPtr>("AppContainerRegisterSid"); |
|
110 } |
|
111 |
|
112 ResultCode operation_result = SBOX_ERROR_GENERIC; |
|
113 if (AppContainerRegisterSid) { |
|
114 HRESULT rv = AppContainerRegisterSid(local_sid, name.c_str(), name.c_str()); |
|
115 if (SUCCEEDED(rv)) |
|
116 operation_result = SBOX_ALL_OK; |
|
117 else |
|
118 DLOG(ERROR) << "AppContainerRegisterSid error:" << std::hex << rv; |
|
119 } |
|
120 LocalFree(local_sid); |
|
121 return operation_result; |
|
122 } |
|
123 |
|
124 ResultCode DeleteAppContainer(const string16& sid) { |
|
125 PSID local_sid; |
|
126 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) |
|
127 return SBOX_ERROR_INVALID_APP_CONTAINER; |
|
128 |
|
129 typedef HRESULT (WINAPI* AppContainerUnregisterSidPtr)(PSID sid); |
|
130 static AppContainerUnregisterSidPtr AppContainerUnregisterSid = NULL; |
|
131 |
|
132 if (!AppContainerUnregisterSid) { |
|
133 AppContainerUnregisterSid = |
|
134 BindFunction<AppContainerUnregisterSidPtr>("AppContainerUnregisterSid"); |
|
135 } |
|
136 |
|
137 ResultCode operation_result = SBOX_ERROR_GENERIC; |
|
138 if (AppContainerUnregisterSid) { |
|
139 HRESULT rv = AppContainerUnregisterSid(local_sid); |
|
140 if (SUCCEEDED(rv)) |
|
141 operation_result = SBOX_ALL_OK; |
|
142 else |
|
143 DLOG(ERROR) << "AppContainerUnregisterSid error:" << std::hex << rv; |
|
144 } |
|
145 LocalFree(local_sid); |
|
146 return operation_result; |
|
147 } |
|
148 |
|
149 string16 LookupAppContainer(const string16& sid) { |
|
150 PSID local_sid; |
|
151 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) |
|
152 return string16(); |
|
153 |
|
154 typedef HRESULT (WINAPI* AppContainerLookupMonikerPtr)(PSID sid, |
|
155 LPWSTR* moniker); |
|
156 typedef BOOLEAN (WINAPI* AppContainerFreeMemoryPtr)(void* ptr); |
|
157 |
|
158 static AppContainerLookupMonikerPtr AppContainerLookupMoniker = NULL; |
|
159 static AppContainerFreeMemoryPtr AppContainerFreeMemory = NULL; |
|
160 |
|
161 if (!AppContainerLookupMoniker || !AppContainerFreeMemory) { |
|
162 AppContainerLookupMoniker = |
|
163 BindFunction<AppContainerLookupMonikerPtr>("AppContainerLookupMoniker"); |
|
164 AppContainerFreeMemory = |
|
165 BindFunction<AppContainerFreeMemoryPtr>("AppContainerFreeMemory"); |
|
166 } |
|
167 |
|
168 if (!AppContainerLookupMoniker || !AppContainerFreeMemory) |
|
169 return string16(); |
|
170 |
|
171 wchar_t* buffer = NULL; |
|
172 HRESULT rv = AppContainerLookupMoniker(local_sid, &buffer); |
|
173 if (FAILED(rv)) |
|
174 return string16(); |
|
175 |
|
176 string16 name(buffer); |
|
177 if (!AppContainerFreeMemory(buffer)) |
|
178 NOTREACHED(); |
|
179 return name; |
|
180 } |
|
181 |
|
182 } // namespace sandbox |