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 |
11 #ifndef SECURITY_APP_PACKAGE_AUTHORITY | |
12 #define SECURITY_APP_PACKAGE_AUTHORITY {0,0,0,0,0,15} | |
13 #endif | |
14 | 11 |
15 std::wstring Communication::browserSID; | |
16 | 12 |
17 namespace | 13 namespace |
18 { | 14 { |
19 const int bufferSize = 1024; | 15 const int bufferSize = 1024; |
20 | 16 |
21 std::string AppendErrorCode(const std::string& message) | 17 std::string AppendErrorCode(const std::string& message) |
22 { | 18 { |
23 std::stringstream stream; | 19 std::stringstream stream; |
24 stream << message << " (Error code: " << GetLastError() << ")"; | 20 stream << message << " (Error code: " << GetLastError() << ")"; |
25 return stream.str(); | 21 return stream.str(); |
(...skipping 23 matching lines...) Expand all Loading... |
49 if (tokenGroups->GroupCount != 1) | 45 if (tokenGroups->GroupCount != 1) |
50 throw std::runtime_error("Unexpected group count"); | 46 throw std::runtime_error("Unexpected group count"); |
51 | 47 |
52 DWORD sidLength = GetLengthSid(tokenGroups->Groups[0].Sid); | 48 DWORD sidLength = GetLengthSid(tokenGroups->Groups[0].Sid); |
53 std::auto_ptr<SID> sid(new SID[sidLength]); | 49 std::auto_ptr<SID> sid(new SID[sidLength]); |
54 if (!CopySid(sidLength, sid.get(), tokenGroups->Groups[0].Sid)) | 50 if (!CopySid(sidLength, sid.get(), tokenGroups->Groups[0].Sid)) |
55 throw std::runtime_error("CopySid failed"); | 51 throw std::runtime_error("CopySid failed"); |
56 return sid; | 52 return sid; |
57 } | 53 } |
58 | 54 |
59 std::auto_ptr<SECURITY_DESCRIPTOR> CreateObjectSecurityDescriptor(PSID logonSi
d) | 55 // Creates a security descriptor: |
| 56 // Allows ALL access to Logon SID and to all app containers in DACL. |
| 57 // Sets Low Integrity in SACL. |
| 58 std::auto_ptr<SECURITY_DESCRIPTOR> CreateSecurityDescriptor(PSID logonSid) |
60 { | 59 { |
61 PSID browserSid = 0; | |
62 std::tr1::shared_ptr<SID> sharedBrowserSid(reinterpret_cast<SID*>(browserSid
), FreeSid); // Just to simplify cleanup | |
63 ConvertStringSidToSid(Communication::browserSID.c_str(), &browserSid); | |
64 | |
65 EXPLICIT_ACCESSW explicitAccess[2] = {}; | 60 EXPLICIT_ACCESSW explicitAccess[2] = {}; |
66 | 61 |
67 explicitAccess[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGH
TS_ALL; | 62 explicitAccess[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGH
TS_ALL; |
68 explicitAccess[0].grfAccessMode = SET_ACCESS; | 63 explicitAccess[0].grfAccessMode = SET_ACCESS; |
69 explicitAccess[0].grfInheritance= NO_INHERITANCE; | 64 explicitAccess[0].grfInheritance= NO_INHERITANCE; |
70 explicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; | 65 explicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; |
71 explicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_USER; | 66 explicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_USER; |
72 explicitAccess[0].Trustee.ptstrName = static_cast<LPWSTR>(logonSid); | 67 explicitAccess[0].Trustee.ptstrName = static_cast<LPWSTR>(logonSid); |
73 | 68 |
74 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGH
TS_ALL; | 69 std::tr1::shared_ptr<SID> sharedAllAppContainersSid; |
75 explicitAccess[1].grfAccessMode = SET_ACCESS; | 70 // TODO: Would be better to detect if AppContainers are supported instead of
checking the Windows version |
76 explicitAccess[1].grfInheritance= NO_INHERITANCE; | 71 bool isAppContainersSupported = IsAppContainersSupported(); |
77 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; | 72 if (isAppContainersSupported) |
78 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; | 73 { |
79 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(browserSid); | 74 // Create a well-known SID for the all appcontainers group. |
| 75 // We need to allow access to all AppContainers, since, apparently, |
| 76 // giving access to specific AppContainer (for example AppContainer of IE)
|
| 77 // tricks Windows into thinking that token is IN AppContainer. |
| 78 // Which blocks all the calls from outside, making it impossible to commun
icate |
| 79 // with the engine when IE is launched with different security settings. |
| 80 PSID allAppContainersSid = 0; |
| 81 SID_IDENTIFIER_AUTHORITY applicationAuthority = SECURITY_APP_PACKAGE_AUTHO
RITY; |
80 | 82 |
| 83 AllocateAndInitializeSid(&applicationAuthority, |
| 84 SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT, |
| 85 SECURITY_APP_PACKAGE_BASE_RID, |
| 86 SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE, |
| 87 0, 0, 0, 0, 0, 0, |
| 88 &allAppContainersSid); |
| 89 sharedAllAppContainersSid.reset(static_cast<SID*>(allAppContainersSid), Fr
eeSid); // Just to simplify cleanup |
| 90 |
| 91 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI
GHTS_ALL; |
| 92 explicitAccess[1].grfAccessMode = SET_ACCESS; |
| 93 explicitAccess[1].grfInheritance= NO_INHERITANCE; |
| 94 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; |
| 95 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; |
| 96 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(allAppContainers
Sid); |
| 97 } |
81 PACL acl = 0; | 98 PACL acl = 0; |
82 std::tr1::shared_ptr<ACL> sharedAcl(acl, FreeSid); // Just to simplify clean
up | 99 if (SetEntriesInAcl(isAppContainersSupported ? 2 : 1, explicitAccess, 0, &ac
l) != ERROR_SUCCESS) |
83 if (SetEntriesInAcl(2, explicitAccess, 0, &acl) != ERROR_SUCCESS) | |
84 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 100 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
| 101 std::tr1::shared_ptr<ACL> sharedAcl(static_cast<ACL*>(acl), LocalFree); // J
ust to simplify cleanup |
85 | 102 |
86 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor(new SECURITY_DESCRIPTO
R[SECURITY_DESCRIPTOR_MIN_LENGTH]); | 103 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor((SECURITY_DESCRIPTOR*)
new char[SECURITY_DESCRIPTOR_MIN_LENGTH]); |
87 if (!InitializeSecurityDescriptor(securityDescriptor.get(), SECURITY_DESCRIP
TOR_REVISION)) | 104 if (!InitializeSecurityDescriptor(securityDescriptor.get(), SECURITY_DESCRIP
TOR_REVISION)) |
88 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 105 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
89 | 106 |
90 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE)) | 107 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE)) |
91 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 108 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
92 | 109 |
| 110 // Create a dummy security descriptor with low integrirty preset and copy it
s SACL into ours |
| 111 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; |
| 112 PSECURITY_DESCRIPTOR dummySecurityDescriptorLow; |
| 113 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDD
L_REVISION_1, &dummySecurityDescriptorLow, 0); |
| 114 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedDummySecurityDescriptor(stat
ic_cast<SECURITY_DESCRIPTOR*>(dummySecurityDescriptorLow), LocalFree); // Just t
o simplify cleanup |
| 115 BOOL saclPresent = FALSE; |
| 116 BOOL saclDefaulted = FALSE; |
| 117 PACL sacl; |
| 118 GetSecurityDescriptorSacl(dummySecurityDescriptorLow, &saclPresent, &sacl, &
saclDefaulted); |
| 119 if (saclPresent) |
| 120 { |
| 121 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE
)) |
| 122 { |
| 123 DWORD err = GetLastError(); |
| 124 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
| 125 } |
| 126 } |
| 127 |
93 return securityDescriptor; | 128 return securityDescriptor; |
94 } | 129 } |
95 } | 130 } |
96 | 131 |
97 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_"
+ GetUserName(); | 132 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_"
+ GetUserName(); |
98 | 133 |
99 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType
) | 134 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType
) |
100 { | 135 { |
101 if (!hasType) | 136 if (!hasType) |
102 ReadBinary(currentType); | 137 ReadBinary(currentType); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 { | 174 { |
140 pipe = INVALID_HANDLE_VALUE; | 175 pipe = INVALID_HANDLE_VALUE; |
141 if (mode == MODE_CREATE) | 176 if (mode == MODE_CREATE) |
142 { | 177 { |
143 SECURITY_ATTRIBUTES securityAttributes = {}; | 178 SECURITY_ATTRIBUTES securityAttributes = {}; |
144 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); | 179 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); |
145 securityAttributes.bInheritHandle = TRUE; | 180 securityAttributes.bInheritHandle = TRUE; |
146 | 181 |
147 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just
to simplify cleanup | 182 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just
to simplify cleanup |
148 | 183 |
149 const bool inAppContainer = !browserSID.empty(); | 184 AutoHandle token; |
150 if (inAppContainer) | 185 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); |
151 { | 186 std::auto_ptr<SID> logonSid = GetLogonSid(token); |
152 AutoHandle token; | 187 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acces
s to all AppContainers |
153 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); | 188 // This is needed since IE likes to jump out of Enhanced Protected Mode for
specific pages (bing.com) |
154 std::auto_ptr<SID> logonSid = GetLogonSid(token); | 189 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateSecurityDescri
ptor(logonSid.get()); |
155 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateObjectSecuri
tyDescriptor(logonSid.get()); | 190 securityAttributes.lpSecurityDescriptor = securityDescriptor.release(); |
156 securityAttributes.lpSecurityDescriptor = securityDescriptor.release(); | 191 sharedSecurityDescriptor.reset(static_cast<SECURITY_DESCRIPTOR*>(securityAtt
ributes.lpSecurityDescriptor)); |
157 sharedSecurityDescriptor.reset(static_cast<SECURITY_DESCRIPTOR*>(securityA
ttributes.lpSecurityDescriptor)); | |
158 } | |
159 else if (IsWindowsVistaOrLater()) | |
160 { | |
161 // Low mandatory label. See http://msdn.microsoft.com/en-us/library/bb6259
58.aspx | |
162 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; | |
163 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, S
DDL_REVISION_1, | |
164 &securityAttributes.lpSecurityDescriptor, 0); | |
165 sharedSecurityDescriptor.reset(static_cast<SECURITY_DESCRIPTOR*>(securityA
ttributes.lpSecurityDescriptor), LocalFree); | |
166 } | |
167 | 192 |
168 pipe = CreateNamedPipeW(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES
SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, | 193 pipe = CreateNamedPipeW(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES
SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, |
169 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &securityAttributes); | 194 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &securityAttributes); |
| 195 |
170 } | 196 } |
171 else | 197 else |
172 { | 198 { |
173 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE
N_EXISTING, 0, 0); | 199 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE
N_EXISTING, 0, 0); |
174 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) | 200 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) |
175 { | 201 { |
176 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) | 202 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) |
177 throw PipeBusyError(); | 203 throw PipeBusyError(); |
178 | 204 |
179 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O
PEN_EXISTING, 0, 0); | 205 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O
PEN_EXISTING, 0, 0); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 return Communication::InputBuffer(stream.str()); | 252 return Communication::InputBuffer(stream.str()); |
227 } | 253 } |
228 | 254 |
229 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) | 255 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) |
230 { | 256 { |
231 DWORD bytesWritten; | 257 DWORD bytesWritten; |
232 std::string data = message.Get(); | 258 std::string data = message.Get(); |
233 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr
itten, 0)) | 259 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr
itten, 0)) |
234 throw std::runtime_error("Failed to write to pipe"); | 260 throw std::runtime_error("Failed to write to pipe"); |
235 } | 261 } |
OLD | NEW |