Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/shared/Communication.cpp

Issue 6308231068516352: Fix issues with security tokens (Enhanced Protected Mode, Protected Mode etc) (Closed)
Patch Set: Created Nov. 15, 2013, 7:22 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld