Left: | ||
Right: |
OLD | NEW |
---|---|
1 #include <Windows.h> | 1 #include <Windows.h> |
2 #include <Lmcons.h> | 2 #include <Lmcons.h> |
3 #include <Sddl.h> | 3 #include <Sddl.h> |
4 #include <aclapi.h> | 4 #include <aclapi.h> |
5 #include <strsafe.h> | 5 #include <strsafe.h> |
6 | 6 |
7 #include "AutoHandle.h" | 7 #include "AutoHandle.h" |
8 #include "Communication.h" | 8 #include "Communication.h" |
9 #include "Utils.h" | 9 #include "Utils.h" |
10 | 10 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 { | 66 { |
67 EXPLICIT_ACCESSW explicitAccess[2] = {}; | 67 EXPLICIT_ACCESSW explicitAccess[2] = {}; |
68 | 68 |
69 explicitAccess[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL; | 69 explicitAccess[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL; |
70 explicitAccess[0].grfAccessMode = SET_ACCESS; | 70 explicitAccess[0].grfAccessMode = SET_ACCESS; |
71 explicitAccess[0].grfInheritance= NO_INHERITANCE; | 71 explicitAccess[0].grfInheritance= NO_INHERITANCE; |
72 explicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; | 72 explicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; |
73 explicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_USER; | 73 explicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_USER; |
74 explicitAccess[0].Trustee.ptstrName = static_cast<LPWSTR>(logonSid); | 74 explicitAccess[0].Trustee.ptstrName = static_cast<LPWSTR>(logonSid); |
75 | 75 |
76 std::tr1::shared_ptr<SID> sharedAllAppContainersSid; | |
77 | |
78 // Create a well-known SID for the all appcontainers group. | 76 // Create a well-known SID for the all appcontainers group. |
79 // We need to allow access to all AppContainers, since, apparently, | 77 // We need to allow access to all AppContainers, since, apparently, |
80 // giving access to specific AppContainer (for example AppContainer of IE) | 78 // giving access to specific AppContainer (for example AppContainer of IE) |
81 // tricks Windows into thinking that token is IN AppContainer. | 79 // tricks Windows into thinking that token is IN AppContainer. |
82 // Which blocks all the calls from outside, making it impossible to commun icate | 80 // Which blocks all the calls from outside, making it impossible to commun icate |
83 // with the engine when IE is launched with different security settings. | 81 // with the engine when IE is launched with different security settings. |
84 PSID allAppContainersSid = 0; | 82 PSID allAppContainersSid = 0; |
85 SID_IDENTIFIER_AUTHORITY applicationAuthority = SECURITY_APP_PACKAGE_AUTHO RITY; | 83 SID_IDENTIFIER_AUTHORITY applicationAuthority = SECURITY_APP_PACKAGE_AUTHO RITY; |
86 | 84 |
87 AllocateAndInitializeSid(&applicationAuthority, | 85 AllocateAndInitializeSid(&applicationAuthority, |
88 SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT, | 86 SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT, |
89 SECURITY_APP_PACKAGE_BASE_RID, | 87 SECURITY_APP_PACKAGE_BASE_RID, |
90 SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE, | 88 SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE, |
91 0, 0, 0, 0, 0, 0, | 89 0, 0, 0, 0, 0, 0, |
92 &allAppContainersSid); | 90 &allAppContainersSid); |
93 sharedAllAppContainersSid.reset(static_cast<SID*>(allAppContainersSid), Fr eeSid); // Just to simplify cleanup | 91 std::tr1::shared_ptr<SID> sharedAllAppContainersSid(static_cast<SID*>(allA ppContainersSid), FreeSid); // Just to simplify cleanup |
94 | 92 |
95 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL; | 93 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL; |
96 explicitAccess[1].grfAccessMode = SET_ACCESS; | 94 explicitAccess[1].grfAccessMode = SET_ACCESS; |
97 explicitAccess[1].grfInheritance= NO_INHERITANCE; | 95 explicitAccess[1].grfInheritance= NO_INHERITANCE; |
98 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; | 96 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; |
99 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; | 97 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; |
100 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(allAppContainers Sid); | 98 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(allAppContainers Sid); |
101 | 99 |
102 PACL acl = 0; | 100 PACL acl = 0; |
101 // acl has to be released after this | |
Felix Dahlke
2014/07/03 13:38:07
I don't really understand, it has to be released a
Oleksandr
2014/07/03 13:51:49
1. This allocates a new ACL, so it has to be relea
Felix Dahlke
2014/07/03 13:56:33
The comment is on top of "SetEntries", so I presum
| |
103 if (SetEntriesInAcl(2, explicitAccess, 0, &acl) != ERROR_SUCCESS) | 102 if (SetEntriesInAcl(2, explicitAccess, 0, &acl) != ERROR_SUCCESS) |
104 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 103 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
105 std::tr1::shared_ptr<ACL> sharedAcl(static_cast<ACL*>(acl), LocalFree); // Just to simplify cleanup | |
106 | 104 |
105 // This only references the acl, not copies it | |
Felix Dahlke
2014/07/03 13:38:07
I think this is not necessary, the official docs s
Oleksandr
2014/07/03 13:51:49
I don't really understand your point here. Could y
Felix Dahlke
2014/07/03 13:56:33
My point is that the Microsoft documentation says
Oleksandr
2014/07/15 14:16:55
This comment is quite important, IMHO. It's pretty
Felix Dahlke
2014/07/16 14:40:03
Alright.
| |
107 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE) ) | 106 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE) ) |
108 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 107 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
109 | |
110 } | 108 } |
111 | 109 |
112 // Create a dummy security descriptor with low integrirty preset and copy it s SACL into ours | 110 // Create a dummy security descriptor with low integrirty preset and copy it s SACL into ours |
113 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; | 111 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; |
114 PSECURITY_DESCRIPTOR dummySecurityDescriptorLow; | 112 PSECURITY_DESCRIPTOR dummySecurityDescriptorLow; |
115 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDD L_REVISION_1, &dummySecurityDescriptorLow, 0); | 113 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDD L_REVISION_1, &dummySecurityDescriptorLow, 0); |
116 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedDummySecurityDescriptor(stat ic_cast<SECURITY_DESCRIPTOR*>(dummySecurityDescriptorLow), LocalFree); // Just t o simplify cleanup | 114 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedDummySecurityDescriptor(stat ic_cast<SECURITY_DESCRIPTOR*>(dummySecurityDescriptorLow), LocalFree); // Just t o simplify cleanup |
117 BOOL saclPresent = FALSE; | 115 BOOL saclPresent = FALSE; |
118 BOOL saclDefaulted = FALSE; | 116 BOOL saclDefaulted = FALSE; |
119 PACL sacl; | 117 PACL sacl; |
120 GetSecurityDescriptorSacl(dummySecurityDescriptorLow, &saclPresent, &sacl, & saclDefaulted); | 118 GetSecurityDescriptorSacl(dummySecurityDescriptorLow, &saclPresent, &sacl, & saclDefaulted); |
121 if (saclPresent) | 119 if (saclPresent) |
122 { | 120 { |
123 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE )) | 121 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE )) |
124 { | 122 { |
125 DWORD err = GetLastError(); | 123 DWORD err = GetLastError(); |
126 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 124 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
127 } | 125 } |
128 } | 126 } |
129 | 127 |
130 return securityDescriptor; | 128 return securityDescriptor; |
131 } | 129 } |
132 } | 130 } |
133 | 131 |
132 // Releases the DACL structure in the provided security descriptor | |
Felix Dahlke
2014/07/03 13:38:07
I think the function name communicates this quite
| |
133 void ReleaseDacl(PSECURITY_DESCRIPTOR securityDescriptor) | |
134 { | |
135 BOOL aclPresent = FALSE; | |
136 BOOL aclDefaulted = FALSE; | |
137 PACL acl; | |
138 GetSecurityDescriptorDacl(securityDescriptor, &aclPresent, &acl, &aclDefault ed); | |
139 if (aclPresent) | |
140 { | |
141 LocalFree(acl); | |
142 } | |
143 } | |
134 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); | 144 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); |
135 | 145 |
136 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) | 146 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) |
137 { | 147 { |
138 if (!hasType) | 148 if (!hasType) |
139 ReadBinary(currentType); | 149 ReadBinary(currentType); |
140 | 150 |
141 if (currentType != expectedType) | 151 if (currentType != expectedType) |
142 { | 152 { |
143 // Make sure we don't attempt to read the type again | 153 // Make sure we don't attempt to read the type again |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) | 185 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) |
176 { | 186 { |
177 pipe = INVALID_HANDLE_VALUE; | 187 pipe = INVALID_HANDLE_VALUE; |
178 if (mode == MODE_CREATE) | 188 if (mode == MODE_CREATE) |
179 { | 189 { |
180 SECURITY_ATTRIBUTES securityAttributes = {}; | 190 SECURITY_ATTRIBUTES securityAttributes = {}; |
181 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); | 191 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); |
182 securityAttributes.bInheritHandle = TRUE; | 192 securityAttributes.bInheritHandle = TRUE; |
183 | 193 |
184 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup | 194 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup |
185 | 195 |
Felix Dahlke
2014/07/03 13:38:07
Whitespace change?
| |
186 AutoHandle token; | 196 AutoHandle token; |
187 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); | 197 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); |
188 | 198 |
189 if (IsWindowsVistaOrLater()) | 199 if (IsWindowsVistaOrLater()) |
190 { | 200 { |
191 std::auto_ptr<SID> logonSid = GetLogonSid(token); | 201 std::auto_ptr<SID> logonSid = GetLogonSid(token); |
192 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acc ess to all AppContainers | 202 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acc ess to all AppContainers |
193 // This is needed since IE likes to jump out of Enhanced Protected Mode fo r specific pages (bing.com) | 203 // This is needed since IE likes to jump out of Enhanced Protected Mode fo r specific pages (bing.com) |
204 | |
205 // ATTENTION: DACL in the returned securityDescriptor has to be manually r eleased by ReleaseDacl | |
194 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateSecurityDesc riptor(logonSid.get()); | 206 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateSecurityDesc riptor(logonSid.get()); |
207 | |
195 securityAttributes.lpSecurityDescriptor = securityDescriptor.release(); | 208 securityAttributes.lpSecurityDescriptor = securityDescriptor.release(); |
196 sharedSecurityDescriptor.reset(static_cast<SECURITY_DESCRIPTOR*>(securityA ttributes.lpSecurityDescriptor)); | 209 sharedSecurityDescriptor.reset(static_cast<SECURITY_DESCRIPTOR*>(securityA ttributes.lpSecurityDescriptor)); |
197 } | 210 } |
198 pipe = CreateNamedPipeW(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, | 211 pipe = CreateNamedPipeW(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, |
199 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &securityAttributes); | 212 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &securityAttributes); |
213 | |
214 if (IsWindowsVistaOrLater()) | |
215 { | |
216 ReleaseDacl(securityAttributes.lpSecurityDescriptor); | |
Felix Dahlke
2014/07/03 13:38:07
Wouldn't it'd be cleaner to put this in a custom f
| |
217 } | |
200 } | 218 } |
201 else | 219 else |
202 { | 220 { |
203 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0); | 221 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0); |
204 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) | 222 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) |
205 { | 223 { |
206 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) | 224 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) |
207 throw PipeBusyError(); | 225 throw PipeBusyError(); |
208 | 226 |
209 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0); | 227 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0); |
210 } | 228 } |
211 } | 229 } |
212 | 230 |
213 if (pipe == INVALID_HANDLE_VALUE) | 231 if (pipe == INVALID_HANDLE_VALUE) |
214 throw PipeConnectionError(); | 232 throw PipeConnectionError(); |
215 | 233 |
216 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; | 234 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; |
217 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0)) | 235 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0)) |
218 throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastE rror()); | 236 throw std::runtime_error(AppendErrorCode("SetNamedPipeHandleState failed")); |
219 | 237 |
220 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0)) | 238 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0)) |
221 { | 239 { |
222 DWORD err = GetLastError(); | 240 DWORD err = GetLastError(); |
223 throw std::runtime_error("Client failed to connect: error " + GetLastError() ); | 241 throw std::runtime_error(AppendErrorCode("Client failed to connect")); |
224 } | 242 } |
225 } | 243 } |
226 | 244 |
227 Communication::Pipe::~Pipe() | 245 Communication::Pipe::~Pipe() |
228 { | 246 { |
229 CloseHandle(pipe); | 247 CloseHandle(pipe); |
230 } | 248 } |
231 | 249 |
232 Communication::InputBuffer Communication::Pipe::ReadMessage() | 250 Communication::InputBuffer Communication::Pipe::ReadMessage() |
233 { | 251 { |
(...skipping 25 matching lines...) Expand all Loading... | |
259 return Communication::InputBuffer(stream.str()); | 277 return Communication::InputBuffer(stream.str()); |
260 } | 278 } |
261 | 279 |
262 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) | 280 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) |
263 { | 281 { |
264 DWORD bytesWritten; | 282 DWORD bytesWritten; |
265 std::string data = message.Get(); | 283 std::string data = message.Get(); |
266 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) | 284 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) |
267 throw std::runtime_error("Failed to write to pipe"); | 285 throw std::runtime_error("Failed to write to pipe"); |
268 } | 286 } |
OLD | NEW |