Left: | ||
Right: |
LEFT | RIGHT |
---|---|
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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 DWORD sidLength = GetLengthSid(tokenGroups->Groups[0].Sid); | 48 DWORD sidLength = GetLengthSid(tokenGroups->Groups[0].Sid); |
49 std::auto_ptr<SID> sid(new SID[sidLength]); | 49 std::auto_ptr<SID> sid(new SID[sidLength]); |
50 if (!CopySid(sidLength, sid.get(), tokenGroups->Groups[0].Sid)) | 50 if (!CopySid(sidLength, sid.get(), tokenGroups->Groups[0].Sid)) |
51 throw std::runtime_error("CopySid failed"); | 51 throw std::runtime_error("CopySid failed"); |
52 return sid; | 52 return sid; |
53 } | 53 } |
54 | 54 |
55 // Creates a security descriptor: | 55 // Creates a security descriptor: |
56 // Allows ALL access to Logon SID and to all app containers in DACL. | 56 // Allows ALL access to Logon SID and to all app containers in DACL. |
57 // Sets Low Integrity in SACL. | 57 // Sets Low Integrity in SACL. |
58 std::auto_ptr<SECURITY_DESCRIPTOR> CreateSecurityDescriptor(PSID logonSid) | 58 std::auto_ptr<SECURITY_DESCRIPTOR> CreateSecurityDescriptor(PSID logonSid) |
Eric
2014/06/25 16:13:00
We can use unique_ptr here. VS2012 supports it.
I
Felix Dahlke
2014/06/25 16:17:13
We really shouldn't mix switching from TR1 shared
| |
59 { | 59 { |
60 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor((SECURITY_DESCRIPTOR*) new char[SECURITY_DESCRIPTOR_MIN_LENGTH]); | 60 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor((SECURITY_DESCRIPTOR*) new char[SECURITY_DESCRIPTOR_MIN_LENGTH]); |
61 if (!InitializeSecurityDescriptor(securityDescriptor.get(), SECURITY_DESCRIP TOR_REVISION)) | 61 if (!InitializeSecurityDescriptor(securityDescriptor.get(), SECURITY_DESCRIP TOR_REVISION)) |
62 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 62 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
63 // TODO: Would be better to detect if AppContainers are supported instead of checking the Windows version | 63 // TODO: Would be better to detect if AppContainers are supported instead of checking the Windows version |
64 bool isAppContainersSupported = IsWindows8OrLater(); | 64 bool isAppContainersSupported = IsWindows8OrLater(); |
65 if (isAppContainersSupported) | 65 if (isAppContainersSupported) |
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 | |
76 std::tr1::shared_ptr<SID> sharedAllAppContainersSid; | |
Eric
2014/06/25 16:13:00
This declaration doesn't need to be separate, but
| |
77 | 75 |
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 |
Eric
2014/06/25 16:13:00
We can use a constructor here instead of reset().
| |
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 |
100 // Will be released later | |
102 PACL acl = 0; | 101 PACL acl = 0; |
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 | 104 |
Wladimir Palant
2014/05/15 07:36:18
If this is just to simplify cleanup, why not use u
| |
106 | 105 // NOTE: This only references the acl, not copies it. |
106 // DO NOT release the ACL before it's actually used | |
107 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE) ) | 107 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE) ) |
108 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 108 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
109 | 109 } |
110 } | 110 |
111 | 111 // Create a dummy security descriptor with low integrirty preset and referen ce its SACL in ours |
112 // Create a dummy security descriptor with low integrirty preset and copy it s SACL into ours | |
113 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; | 112 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; |
114 PSECURITY_DESCRIPTOR dummySecurityDescriptorLow; | 113 PSECURITY_DESCRIPTOR dummySecurityDescriptorLow; |
115 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDD L_REVISION_1, &dummySecurityDescriptorLow, 0); | 114 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 | 115 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedDummySecurityDescriptor(stat ic_cast<SECURITY_DESCRIPTOR*>(dummySecurityDescriptorLow), LocalFree); // Just t o simplify cleanup |
117 BOOL saclPresent = FALSE; | 116 |
118 BOOL saclDefaulted = FALSE; | 117 DWORD sdSize(0), saclSize(0), daclSize(0), ownerSize(0), primaryGroupSize(0) ; |
119 PACL sacl; | 118 MakeAbsoluteSD(dummySecurityDescriptorLow, 0, &sdSize, 0, &daclSize, 0, &sac lSize, 0, &ownerSize, 0, &primaryGroupSize); |
120 GetSecurityDescriptorSacl(dummySecurityDescriptorLow, &saclPresent, &sacl, & saclDefaulted); | 119 if (saclSize == 0 || sdSize == 0) |
121 if (saclPresent) | 120 { |
122 { | |
123 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE )) | |
124 { | |
125 DWORD err = GetLastError(); | |
126 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 121 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
127 } | 122 } |
123 // Will be released later | |
124 PACL sacl = static_cast<PACL>(malloc(saclSize)); | |
125 std::auto_ptr<SECURITY_DESCRIPTOR> absoluteDummySecurityDescriptorLow(static _cast<SECURITY_DESCRIPTOR*>(malloc(sdSize))); | |
126 daclSize = 0; | |
127 ownerSize = 0; | |
128 primaryGroupSize = 0; | |
129 BOOL res = MakeAbsoluteSD(dummySecurityDescriptorLow, absoluteDummySecurityD escriptorLow.get(), &sdSize, 0, &daclSize, sacl, &saclSize, 0, &ownerSize, 0, &p rimaryGroupSize); | |
130 if (res == 0 || absoluteDummySecurityDescriptorLow.get() == 0 || saclSize == 0) | |
131 { | |
132 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | |
133 } | |
134 | |
135 // NOTE: This only references the acl, not copies it. | |
136 // DO NOT release the ACL before it's actually used | |
137 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE)) | |
138 { | |
139 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | |
128 } | 140 } |
129 | 141 |
130 return securityDescriptor; | 142 return securityDescriptor; |
131 } | 143 } |
132 } | 144 } |
133 | 145 |
134 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); | 146 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); |
135 | 147 |
136 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) | 148 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) |
137 { | 149 { |
(...skipping 27 matching lines...) Expand all Loading... | |
165 Communication::PipeBusyError::PipeBusyError() | 177 Communication::PipeBusyError::PipeBusyError() |
166 : std::runtime_error("Timeout while trying to connect to a named pipe, pipe is busy") | 178 : std::runtime_error("Timeout while trying to connect to a named pipe, pipe is busy") |
167 { | 179 { |
168 } | 180 } |
169 | 181 |
170 Communication::PipeDisconnectedError::PipeDisconnectedError() | 182 Communication::PipeDisconnectedError::PipeDisconnectedError() |
171 : std::runtime_error("Pipe disconnected") | 183 : std::runtime_error("Pipe disconnected") |
172 { | 184 { |
173 } | 185 } |
174 | 186 |
187 void FreeAbsoluteSecurityDescriptor(SECURITY_DESCRIPTOR* securityDescriptor) | |
188 { | |
189 BOOL aclPresent = FALSE; | |
190 BOOL aclDefaulted = FALSE; | |
191 PACL acl = 0; | |
192 GetSecurityDescriptorDacl(securityDescriptor, &aclPresent, &acl, &aclDefaulted ); | |
193 if (aclPresent) | |
194 { | |
195 LocalFree(acl); | |
196 } | |
197 aclPresent = FALSE; | |
198 aclDefaulted = FALSE; | |
199 acl = 0; | |
200 GetSecurityDescriptorSacl(securityDescriptor, &aclPresent, &acl, &aclDefaulted ); | |
201 if (aclPresent) | |
202 { | |
203 free(acl); | |
204 } | |
205 free(securityDescriptor); | |
206 } | |
207 | |
175 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) | 208 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) |
176 { | 209 { |
177 pipe = INVALID_HANDLE_VALUE; | 210 pipe = INVALID_HANDLE_VALUE; |
178 if (mode == MODE_CREATE) | 211 if (mode == MODE_CREATE) |
179 { | 212 { |
180 | |
Wladimir Palant
2014/05/15 07:36:18
Nit: don't add an empty line here.
| |
181 SECURITY_ATTRIBUTES securityAttributes = {}; | 213 SECURITY_ATTRIBUTES securityAttributes = {}; |
182 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); | 214 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); |
183 securityAttributes.bInheritHandle = TRUE; | 215 securityAttributes.bInheritHandle = TRUE; |
184 | 216 |
185 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup | 217 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup |
186 | |
187 AutoHandle token; | 218 AutoHandle token; |
188 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); | 219 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); |
189 std::auto_ptr<SID> logonSid = GetLogonSid(token); | 220 |
190 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acces s to all AppContainers | 221 if (IsWindowsVistaOrLater()) |
191 // This is needed since IE likes to jump out of Enhanced Protected Mode for specific pages (bing.com) | 222 { |
192 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateSecurityDescri ptor(logonSid.get()); | 223 std::auto_ptr<SID> logonSid = GetLogonSid(token); |
193 securityAttributes.lpSecurityDescriptor = securityDescriptor.release(); | 224 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acc ess to all AppContainers |
194 sharedSecurityDescriptor.reset(static_cast<SECURITY_DESCRIPTOR*>(securityAtt ributes.lpSecurityDescriptor)); | 225 // This is needed since IE likes to jump out of Enhanced Protected Mode fo r specific pages (bing.com) |
195 | 226 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateSecurityDesc riptor(logonSid.get()); |
227 | |
228 securityAttributes.lpSecurityDescriptor = securityDescriptor.release(); | |
229 sharedSecurityDescriptor.reset(static_cast<SECURITY_DESCRIPTOR*>(securityA ttributes.lpSecurityDescriptor), FreeAbsoluteSecurityDescriptor); | |
230 } | |
196 pipe = CreateNamedPipeW(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, | 231 pipe = CreateNamedPipeW(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, |
197 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &securityAttributes); | 232 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &securityAttributes); |
198 | |
199 } | 233 } |
200 else | 234 else |
201 { | 235 { |
202 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0); | 236 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0); |
203 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) | 237 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) |
204 { | 238 { |
205 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) | 239 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) |
206 throw PipeBusyError(); | 240 throw PipeBusyError(); |
207 | 241 |
208 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0); | 242 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0); |
209 } | 243 } |
210 } | 244 } |
211 | 245 |
212 if (pipe == INVALID_HANDLE_VALUE) | 246 if (pipe == INVALID_HANDLE_VALUE) |
213 throw PipeConnectionError(); | 247 throw PipeConnectionError(); |
214 | 248 |
215 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; | 249 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; |
216 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0)) | 250 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0)) |
217 throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastE rror()); | 251 throw std::runtime_error(AppendErrorCode("SetNamedPipeHandleState failed")); |
218 | 252 |
219 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0)) | 253 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0)) |
220 { | 254 { |
221 DWORD err = GetLastError(); | 255 DWORD err = GetLastError(); |
Wladimir Palant
2014/05/15 07:36:18
Why create a variable and not use it then?
| |
222 throw std::runtime_error("Client failed to connect: error " + GetLastError() ); | 256 throw std::runtime_error(AppendErrorCode("Client failed to connect")); |
Wladimir Palant
2014/05/15 07:36:18
Does this actually work? IMHO this adds an int to
| |
223 } | 257 } |
224 } | 258 } |
225 | 259 |
226 Communication::Pipe::~Pipe() | 260 Communication::Pipe::~Pipe() |
227 { | 261 { |
228 CloseHandle(pipe); | 262 CloseHandle(pipe); |
229 } | 263 } |
230 | 264 |
231 Communication::InputBuffer Communication::Pipe::ReadMessage() | 265 Communication::InputBuffer Communication::Pipe::ReadMessage() |
232 { | 266 { |
(...skipping 25 matching lines...) Expand all Loading... | |
258 return Communication::InputBuffer(stream.str()); | 292 return Communication::InputBuffer(stream.str()); |
259 } | 293 } |
260 | 294 |
261 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) | 295 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) |
262 { | 296 { |
263 DWORD bytesWritten; | 297 DWORD bytesWritten; |
264 std::string data = message.Get(); | 298 std::string data = message.Get(); |
265 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) | 299 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) |
266 throw std::runtime_error("Failed to write to pipe"); | 300 throw std::runtime_error("Failed to write to pipe"); |
267 } | 301 } |
LEFT | RIGHT |