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 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 EXPLICIT_ACCESSW explicitAccess[2] = {}; | 60 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor((SECURITY_DESCRIPTOR*) new char[SECURITY_DESCRIPTOR_MIN_LENGTH]); |
61 | 61 if (!InitializeSecurityDescriptor(securityDescriptor.get(), SECURITY_DESCRIP TOR_REVISION)) |
62 explicitAccess[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGH TS_ALL; | 62 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
63 explicitAccess[0].grfAccessMode = SET_ACCESS; | |
64 explicitAccess[0].grfInheritance= NO_INHERITANCE; | |
65 explicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; | |
66 explicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_USER; | |
67 explicitAccess[0].Trustee.ptstrName = static_cast<LPWSTR>(logonSid); | |
68 | |
69 std::tr1::shared_ptr<SID> sharedAllAppContainersSid; | |
70 // 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 |
71 bool isAppContainersSupported = IsAppContainersSupported(); | 64 bool isAppContainersSupported = IsWindows8OrLater(); |
72 if (isAppContainersSupported) | 65 if (isAppContainersSupported) |
73 { | 66 { |
67 EXPLICIT_ACCESSW explicitAccess[2] = {}; | |
68 | |
69 explicitAccess[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL; | |
70 explicitAccess[0].grfAccessMode = SET_ACCESS; | |
71 explicitAccess[0].grfInheritance= NO_INHERITANCE; | |
72 explicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; | |
73 explicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_USER; | |
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 | |
74 // Create a well-known SID for the all appcontainers group. | 78 // Create a well-known SID for the all appcontainers group. |
75 // We need to allow access to all AppContainers, since, apparently, | 79 // We need to allow access to all AppContainers, since, apparently, |
76 // giving access to specific AppContainer (for example AppContainer of IE) | 80 // giving access to specific AppContainer (for example AppContainer of IE) |
77 // tricks Windows into thinking that token is IN AppContainer. | 81 // tricks Windows into thinking that token is IN AppContainer. |
78 // Which blocks all the calls from outside, making it impossible to commun icate | 82 // 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. | 83 // with the engine when IE is launched with different security settings. |
80 PSID allAppContainersSid = 0; | 84 PSID allAppContainersSid = 0; |
81 SID_IDENTIFIER_AUTHORITY applicationAuthority = SECURITY_APP_PACKAGE_AUTHO RITY; | 85 SID_IDENTIFIER_AUTHORITY applicationAuthority = SECURITY_APP_PACKAGE_AUTHO RITY; |
82 | 86 |
83 AllocateAndInitializeSid(&applicationAuthority, | 87 AllocateAndInitializeSid(&applicationAuthority, |
84 SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT, | 88 SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT, |
85 SECURITY_APP_PACKAGE_BASE_RID, | 89 SECURITY_APP_PACKAGE_BASE_RID, |
86 SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE, | 90 SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE, |
87 0, 0, 0, 0, 0, 0, | 91 0, 0, 0, 0, 0, 0, |
88 &allAppContainersSid); | 92 &allAppContainersSid); |
89 sharedAllAppContainersSid.reset(static_cast<SID*>(allAppContainersSid), Fr eeSid); // Just to simplify cleanup | 93 sharedAllAppContainersSid.reset(static_cast<SID*>(allAppContainersSid), Fr eeSid); // Just to simplify cleanup |
Eric
2014/06/25 16:13:00
We can use a constructor here instead of reset().
| |
90 | 94 |
91 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL; | 95 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL; |
92 explicitAccess[1].grfAccessMode = SET_ACCESS; | 96 explicitAccess[1].grfAccessMode = SET_ACCESS; |
93 explicitAccess[1].grfInheritance= NO_INHERITANCE; | 97 explicitAccess[1].grfInheritance= NO_INHERITANCE; |
94 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; | 98 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; |
95 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; | 99 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; |
96 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(allAppContainers Sid); | 100 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(allAppContainers Sid); |
101 | |
102 PACL acl = 0; | |
103 if (SetEntriesInAcl(2, explicitAccess, 0, &acl) != ERROR_SUCCESS) | |
104 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | |
105 std::tr1::shared_ptr<ACL> sharedAcl(static_cast<ACL*>(acl), LocalFree); // Just to simplify cleanup | |
Wladimir Palant
2014/05/15 07:36:18
If this is just to simplify cleanup, why not use u
| |
106 | |
107 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE) ) | |
108 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | |
109 | |
97 } | 110 } |
98 PACL acl = 0; | |
99 if (SetEntriesInAcl(isAppContainersSupported ? 2 : 1, explicitAccess, 0, &ac l) != ERROR_SUCCESS) | |
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 | |
102 | |
103 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor((SECURITY_DESCRIPTOR*) new char[SECURITY_DESCRIPTOR_MIN_LENGTH]); | |
104 if (!InitializeSecurityDescriptor(securityDescriptor.get(), SECURITY_DESCRIP TOR_REVISION)) | |
105 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | |
106 | |
107 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE)) | |
108 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | |
109 | 111 |
110 // Create a dummy security descriptor with low integrirty preset and copy it s SACL into ours | 112 // Create a dummy security descriptor with low integrirty preset and copy it s SACL into ours |
111 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; | 113 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; |
112 PSECURITY_DESCRIPTOR dummySecurityDescriptorLow; | 114 PSECURITY_DESCRIPTOR dummySecurityDescriptorLow; |
113 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDD L_REVISION_1, &dummySecurityDescriptorLow, 0); | 115 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 | 116 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedDummySecurityDescriptor(stat ic_cast<SECURITY_DESCRIPTOR*>(dummySecurityDescriptorLow), LocalFree); // Just t o simplify cleanup |
115 BOOL saclPresent = FALSE; | 117 BOOL saclPresent = FALSE; |
116 BOOL saclDefaulted = FALSE; | 118 BOOL saclDefaulted = FALSE; |
117 PACL sacl; | 119 PACL sacl; |
118 GetSecurityDescriptorSacl(dummySecurityDescriptorLow, &saclPresent, &sacl, & saclDefaulted); | 120 GetSecurityDescriptorSacl(dummySecurityDescriptorLow, &saclPresent, &sacl, & saclDefaulted); |
119 if (saclPresent) | 121 if (saclPresent) |
120 { | 122 { |
121 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE )) | 123 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE )) |
122 { | 124 { |
123 DWORD err = GetLastError(); | 125 DWORD err = GetLastError(); |
124 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); | 126 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); |
125 } | 127 } |
126 } | 128 } |
127 | 129 |
128 return securityDescriptor; | 130 return securityDescriptor; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 Communication::PipeDisconnectedError::PipeDisconnectedError() | 170 Communication::PipeDisconnectedError::PipeDisconnectedError() |
169 : std::runtime_error("Pipe disconnected") | 171 : std::runtime_error("Pipe disconnected") |
170 { | 172 { |
171 } | 173 } |
172 | 174 |
173 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) | 175 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) |
174 { | 176 { |
175 pipe = INVALID_HANDLE_VALUE; | 177 pipe = INVALID_HANDLE_VALUE; |
176 if (mode == MODE_CREATE) | 178 if (mode == MODE_CREATE) |
177 { | 179 { |
180 | |
Wladimir Palant
2014/05/15 07:36:18
Nit: don't add an empty line here.
| |
178 SECURITY_ATTRIBUTES securityAttributes = {}; | 181 SECURITY_ATTRIBUTES securityAttributes = {}; |
179 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); | 182 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); |
180 securityAttributes.bInheritHandle = TRUE; | 183 securityAttributes.bInheritHandle = TRUE; |
181 | 184 |
182 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup | 185 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup |
183 | 186 |
184 AutoHandle token; | 187 AutoHandle token; |
185 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); | 188 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); |
186 std::auto_ptr<SID> logonSid = GetLogonSid(token); | 189 std::auto_ptr<SID> logonSid = GetLogonSid(token); |
187 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acces s to all AppContainers | 190 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acces s to all AppContainers |
(...skipping 19 matching lines...) Expand all Loading... | |
207 } | 210 } |
208 | 211 |
209 if (pipe == INVALID_HANDLE_VALUE) | 212 if (pipe == INVALID_HANDLE_VALUE) |
210 throw PipeConnectionError(); | 213 throw PipeConnectionError(); |
211 | 214 |
212 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; | 215 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; |
213 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0)) | 216 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0)) |
214 throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastE rror()); | 217 throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastE rror()); |
215 | 218 |
216 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0)) | 219 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0)) |
220 { | |
221 DWORD err = GetLastError(); | |
Wladimir Palant
2014/05/15 07:36:18
Why create a variable and not use it then?
| |
217 throw std::runtime_error("Client failed to connect: error " + GetLastError() ); | 222 throw std::runtime_error("Client failed to connect: error " + GetLastError() ); |
Wladimir Palant
2014/05/15 07:36:18
Does this actually work? IMHO this adds an int to
| |
223 } | |
218 } | 224 } |
219 | 225 |
220 Communication::Pipe::~Pipe() | 226 Communication::Pipe::~Pipe() |
221 { | 227 { |
222 CloseHandle(pipe); | 228 CloseHandle(pipe); |
223 } | 229 } |
224 | 230 |
225 Communication::InputBuffer Communication::Pipe::ReadMessage() | 231 Communication::InputBuffer Communication::Pipe::ReadMessage() |
226 { | 232 { |
227 std::stringstream stream; | 233 std::stringstream stream; |
(...skipping 24 matching lines...) Expand all Loading... | |
252 return Communication::InputBuffer(stream.str()); | 258 return Communication::InputBuffer(stream.str()); |
253 } | 259 } |
254 | 260 |
255 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) | 261 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) |
256 { | 262 { |
257 DWORD bytesWritten; | 263 DWORD bytesWritten; |
258 std::string data = message.Get(); | 264 std::string data = message.Get(); |
259 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) | 265 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) |
260 throw std::runtime_error("Failed to write to pipe"); | 266 throw std::runtime_error("Failed to write to pipe"); |
261 } | 267 } |
OLD | NEW |