| 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 |
| 11 #ifndef SECURITY_APP_PACKAGE_AUTHORITY | 11 |
| 12 // | |
| 13 // Application Package Authority. | |
| 14 // | |
| 15 | |
| 12 #define SECURITY_APP_PACKAGE_AUTHORITY {0,0,0,0,0,15} | 16 #define SECURITY_APP_PACKAGE_AUTHORITY {0,0,0,0,0,15} |
| 13 #endif | |
| 14 | 17 |
| 15 std::wstring Communication::browserSID; | 18 #define SECURITY_APP_PACKAGE_BASE_RID (0x00000002L) |
| 19 #define SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT (2L) | |
| 20 #define SECURITY_APP_PACKAGE_RID_COUNT (8L) | |
| 21 #define SECURITY_CAPABILITY_BASE_RID (0x00000003L) | |
| 22 #define SECURITY_BUILTIN_CAPABILITY_RID_COUNT (2L) | |
| 23 #define SECURITY_CAPABILITY_RID_COUNT (5L) | |
| 24 | |
| 25 // | |
| 26 // Built-in Packages. | |
| 27 // | |
| 28 | |
| 29 #define SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE (0x00000001L) | |
| 16 | 30 |
| 17 namespace | 31 namespace |
| 18 { | 32 { |
| 19 const int bufferSize = 1024; | 33 const int bufferSize = 1024; |
| 20 | 34 |
| 21 std::string AppendErrorCode(const std::string& message) | 35 std::string AppendErrorCode(const std::string& message) |
| 22 { | 36 { |
| 23 std::stringstream stream; | 37 std::stringstream stream; |
| 24 stream << message << " (Error code: " << GetLastError() << ")"; | 38 stream << message << " (Error code: " << GetLastError() << ")"; |
| 25 return stream.str(); | 39 return stream.str(); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 49 if (tokenGroups->GroupCount != 1) | 63 if (tokenGroups->GroupCount != 1) |
| 50 throw std::runtime_error("Unexpected group count"); | 64 throw std::runtime_error("Unexpected group count"); |
| 51 | 65 |
| 52 DWORD sidLength = GetLengthSid(tokenGroups->Groups[0].Sid); | 66 DWORD sidLength = GetLengthSid(tokenGroups->Groups[0].Sid); |
| 53 std::auto_ptr<SID> sid(new SID[sidLength]); | 67 std::auto_ptr<SID> sid(new SID[sidLength]); |
| 54 if (!CopySid(sidLength, sid.get(), tokenGroups->Groups[0].Sid)) | 68 if (!CopySid(sidLength, sid.get(), tokenGroups->Groups[0].Sid)) |
| 55 throw std::runtime_error("CopySid failed"); | 69 throw std::runtime_error("CopySid failed"); |
| 56 return sid; | 70 return sid; |
| 57 } | 71 } |
| 58 | 72 |
| 59 std::auto_ptr<SECURITY_DESCRIPTOR> CreateObjectSecurityDescriptor(PSID logonSi d) | 73 // Creates a security descriptor: |
| 74 // Allows ALL access to Logon SID and to all app containers in DACL. | |
| 75 // Sets Low Integrity in SACL. | |
| 76 std::auto_ptr<SECURITY_DESCRIPTOR> CreateSecurityDescriptorLowAndAppContainers (PSID logonSid) | |
|
Felix Dahlke
2013/12/10 16:46:36
I don't think we need to put the specifics of the
| |
| 60 { | 77 { |
| 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] = {}; | 78 EXPLICIT_ACCESSW explicitAccess[2] = {}; |
| 66 | 79 |
| 67 explicitAccess[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGH TS_ALL; | 80 explicitAccess[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGH TS_ALL; |
| 68 explicitAccess[0].grfAccessMode = SET_ACCESS; | 81 explicitAccess[0].grfAccessMode = SET_ACCESS; |
| 69 explicitAccess[0].grfInheritance= NO_INHERITANCE; | 82 explicitAccess[0].grfInheritance= NO_INHERITANCE; |
| 70 explicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; | 83 explicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; |
| 71 explicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_USER; | 84 explicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_USER; |
| 72 explicitAccess[0].Trustee.ptstrName = static_cast<LPWSTR>(logonSid); | 85 explicitAccess[0].Trustee.ptstrName = static_cast<LPWSTR>(logonSid); |
| 73 | 86 |
| 74 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGH TS_ALL; | 87 std::tr1::shared_ptr<SID> sharedAllAppContainersSid; |
| 75 explicitAccess[1].grfAccessMode = SET_ACCESS; | 88 // TODO: Would be better to detect if AppContainers are supported instead of checking the Windows version |
| 76 explicitAccess[1].grfInheritance= NO_INHERITANCE; | 89 bool isWindows8 = IsWindows8(); |
|
Felix Dahlke
2013/12/10 16:46:36
Agreed, would be better to check for app container
| |
| 77 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; | 90 if (isWindows8) |
| 78 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; | 91 { |
| 79 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(browserSid); | 92 PSID allAppContainersSid = 0; |
| 93 SID_IDENTIFIER_AUTHORITY ApplicationAuthority = SECURITY_APP_PACKAGE_AUTHO RITY; | |
|
Felix Dahlke
2013/12/10 16:46:36
Variables should start with a lower case letter.
| |
| 80 | 94 |
| 95 // Create a well-known SID for the all appcontainers group. | |
|
Felix Dahlke
2013/12/10 16:46:36
I think it'd make sense to move this comment in fr
| |
| 96 // We need to allow access to all AppContainers, since, apparently, | |
| 97 // giving access to specific AppContainer (for example AppContainer of IE) | |
| 98 // tricks Windows into thinking that token is IN AppContainer. | |
| 99 // Which blocks all the calls from outside, making it impossible to commun icate | |
| 100 // with engine when IE is launched with different security settings. | |
|
Felix Dahlke
2013/12/10 16:46:36
with "the" engine
| |
| 101 AllocateAndInitializeSid(&ApplicationAuthority, | |
| 102 SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT, | |
| 103 SECURITY_APP_PACKAGE_BASE_RID, | |
| 104 SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE, | |
| 105 0, 0, 0, 0, 0, 0, | |
| 106 &allAppContainersSid); | |
| 107 sharedAllAppContainersSid.reset(static_cast<SID*>(allAppContainersSid), Fr eeSid); // Just to simplify cleanup | |
| 108 | |
| 109 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL; | |
| 110 explicitAccess[1].grfAccessMode = SET_ACCESS; | |
| 111 explicitAccess[1].grfInheritance= NO_INHERITANCE; | |
| 112 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; | |
| 113 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; | |
| 114 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(allAppContainers Sid); | |
| 115 } | |
| 81 PACL acl = 0; | 116 PACL acl = 0; |
| 82 std::tr1::shared_ptr<ACL> sharedAcl(acl, FreeSid); // Just to simplify clean up | 117 if (SetEntriesInAcl(isWindows8 ? 2 : 1, explicitAccess, 0, &acl) != ERROR_SU CCESS) |
| 83 if (SetEntriesInAcl(2, explicitAccess, 0, &acl) != ERROR_SUCCESS) | |
| 84 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 118 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
| 119 std::tr1::shared_ptr<ACL> sharedAcl(static_cast<ACL*>(acl), LocalFree); // J ust to simplify cleanup | |
| 85 | 120 |
| 86 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor(new SECURITY_DESCRIPTO R[SECURITY_DESCRIPTOR_MIN_LENGTH]); | 121 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor((SECURITY_DESCRIPTOR*) new char[SECURITY_DESCRIPTOR_MIN_LENGTH]); |
| 87 if (!InitializeSecurityDescriptor(securityDescriptor.get(), SECURITY_DESCRIP TOR_REVISION)) | 122 if (!InitializeSecurityDescriptor(securityDescriptor.get(), SECURITY_DESCRIP TOR_REVISION)) |
| 88 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 123 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
| 89 | 124 |
| 90 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE)) | 125 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE)) |
| 91 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 126 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
| 92 | 127 |
| 128 // Create a dummy security descriptor with low integrirty preset and copy it s SACL into ours | |
| 129 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; | |
| 130 PSECURITY_DESCRIPTOR pDummySecurityDescriptorLow; | |
|
Felix Dahlke
2013/12/10 16:46:36
Also quite hungarian :)
| |
| 131 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDD L_REVISION_1, &pDummySecurityDescriptorLow, 0); | |
| 132 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedDummySecurityDescriptor(stat ic_cast<SECURITY_DESCRIPTOR*>(pDummySecurityDescriptorLow), LocalFree); // Just to simplify cleanup | |
| 133 BOOL saclPresent = FALSE; | |
| 134 BOOL saclDefaulted = FALSE; | |
| 135 PACL sacl; | |
| 136 GetSecurityDescriptorSacl(pDummySecurityDescriptorLow, &saclPresent, &sacl, &saclDefaulted); | |
| 137 std::tr1::shared_ptr<ACL> sharedSacl(static_cast<ACL*>(sacl), LocalFree); // Just to simplify cleanup | |
| 138 if (saclPresent) | |
| 139 { | |
| 140 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE )) | |
| 141 { | |
| 142 DWORD err = GetLastError(); | |
| 143 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | |
| 144 } | |
| 145 } | |
| 146 | |
| 93 return securityDescriptor; | 147 return securityDescriptor; |
| 94 } | 148 } |
| 95 } | 149 } |
| 96 | 150 |
| 97 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); | 151 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); |
| 98 | 152 |
| 99 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) | 153 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) |
| 100 { | 154 { |
| 101 if (!hasType) | 155 if (!hasType) |
| 102 ReadBinary(currentType); | 156 ReadBinary(currentType); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 { | 193 { |
| 140 pipe = INVALID_HANDLE_VALUE; | 194 pipe = INVALID_HANDLE_VALUE; |
| 141 if (mode == MODE_CREATE) | 195 if (mode == MODE_CREATE) |
| 142 { | 196 { |
| 143 SECURITY_ATTRIBUTES securityAttributes = {}; | 197 SECURITY_ATTRIBUTES securityAttributes = {}; |
| 144 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); | 198 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); |
| 145 securityAttributes.bInheritHandle = TRUE; | 199 securityAttributes.bInheritHandle = TRUE; |
| 146 | 200 |
| 147 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup | 201 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup |
| 148 | 202 |
| 149 const bool inAppContainer = !browserSID.empty(); | 203 AutoHandle token; |
| 150 if (inAppContainer) | 204 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); |
| 151 { | 205 std::auto_ptr<SID> logonSid = GetLogonSid(token); |
| 152 AutoHandle token; | 206 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acces s to all AppContainers |
| 153 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); | 207 // 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); | 208 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateSecurityDescri ptorLowAndAppContainers(logonSid.get()); |
| 155 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateObjectSecuri tyDescriptor(logonSid.get()); | 209 securityAttributes.lpSecurityDescriptor = securityDescriptor.release(); |
| 156 securityAttributes.lpSecurityDescriptor = securityDescriptor.release(); | 210 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 | 211 |
| 168 pipe = CreateNamedPipeW(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, | 212 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); | 213 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &securityAttributes); |
| 214 | |
| 170 } | 215 } |
| 171 else | 216 else |
| 172 { | 217 { |
| 173 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0); | 218 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) | 219 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) |
| 175 { | 220 { |
| 176 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) | 221 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) |
| 177 throw PipeBusyError(); | 222 throw PipeBusyError(); |
| 178 | 223 |
| 179 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0); | 224 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()); | 271 return Communication::InputBuffer(stream.str()); |
| 227 } | 272 } |
| 228 | 273 |
| 229 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) | 274 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) |
| 230 { | 275 { |
| 231 DWORD bytesWritten; | 276 DWORD bytesWritten; |
| 232 std::string data = message.Get(); | 277 std::string data = message.Get(); |
| 233 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) | 278 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) |
| 234 throw std::runtime_error("Failed to write to pipe"); | 279 throw std::runtime_error("Failed to write to pipe"); |
| 235 } | 280 } |
| OLD | NEW |