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

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

Issue 5792731695677440: Fix named pipe security on Windows 7 (Closed)
Patch Set: Use custom free function. Make sure sure SACL is released correctly as well. Created July 15, 2014, 2:13 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 &allAppContainersSid); 90 &allAppContainersSid);
91 std::tr1::shared_ptr<SID> sharedAllAppContainersSid(static_cast<SID*>(allA ppContainersSid), FreeSid); // Just to simplify cleanup 91 std::tr1::shared_ptr<SID> sharedAllAppContainersSid(static_cast<SID*>(allA ppContainersSid), FreeSid); // Just to simplify cleanup
92 92
93 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL; 93 explicitAccess[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RI GHTS_ALL;
94 explicitAccess[1].grfAccessMode = SET_ACCESS; 94 explicitAccess[1].grfAccessMode = SET_ACCESS;
95 explicitAccess[1].grfInheritance= NO_INHERITANCE; 95 explicitAccess[1].grfInheritance= NO_INHERITANCE;
96 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; 96 explicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
97 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; 97 explicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
98 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(allAppContainers Sid); 98 explicitAccess[1].Trustee.ptstrName = static_cast<LPWSTR>(allAppContainers Sid);
99 99
100 // Will be released later
100 PACL acl = 0; 101 PACL acl = 0;
101 // acl has to be released after this
102 if (SetEntriesInAcl(2, explicitAccess, 0, &acl) != ERROR_SUCCESS) 102 if (SetEntriesInAcl(2, explicitAccess, 0, &acl) != ERROR_SUCCESS)
103 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); 103 return std::auto_ptr<SECURITY_DESCRIPTOR>(0);
104 104
105 // This only references the acl, not copies it 105 // NOTE: This only references the acl, not copies it.
106 // DO NOT release the ACL before it's actually used
106 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE) ) 107 if (!SetSecurityDescriptorDacl(securityDescriptor.get(), TRUE, acl, FALSE) )
107 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); 108 return std::auto_ptr<SECURITY_DESCRIPTOR>(0);
108 } 109 }
109 110
110 // Create a dummy security descriptor with low integrirty preset and copy it s SACL into ours 111 // Create a dummy security descriptor with low integrirty preset and reffere nce its SACL in ours
Felix Dahlke 2014/07/16 14:40:03 s/refference/reference/
Oleksandr 2014/07/17 17:32:48 Um. Refference is meant to be a verb here. On 201
Felix Dahlke 2014/07/18 12:40:57 But it's still one f too many! :)
Oleksandr 2014/07/18 12:48:34 Oh. Totally missread your correction. On 2014/07/
111 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; 112 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)";
112 PSECURITY_DESCRIPTOR dummySecurityDescriptorLow; 113 PSECURITY_DESCRIPTOR dummySecurityDescriptorLow;
113 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDD L_REVISION_1, &dummySecurityDescriptorLow, 0); 114 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 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedDummySecurityDescriptor(stat ic_cast<SECURITY_DESCRIPTOR*>(dummySecurityDescriptorLow), LocalFree); // Just t o simplify cleanup
115 BOOL saclPresent = FALSE; 116
116 BOOL saclDefaulted = FALSE; 117 DWORD sdSize, saclSize, daclSize, ownerSize, primaryGroupSize;
Felix Dahlke 2014/07/16 14:40:03 Shouldn't we initialise all the sizes to 0 here? S
117 PACL sacl; 118 MakeAbsoluteSD(dummySecurityDescriptorLow, 0, &sdSize, 0, &daclSize, 0, &sac lSize, 0, &ownerSize, 0, &primaryGroupSize);
118 GetSecurityDescriptorSacl(dummySecurityDescriptorLow, &saclPresent, &sacl, & saclDefaulted); 119 if ((saclSize == 0) || (sdSize == 0))
Felix Dahlke 2014/07/16 14:40:03 Redundant parentheses around both comparisons.
119 if (saclPresent)
120 { 120 {
121 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE ))
122 {
123 DWORD err = GetLastError(); 121 DWORD err = GetLastError();
Felix Dahlke 2014/07/16 14:40:03 Unused variable.
124 return std::auto_ptr<SECURITY_DESCRIPTOR>(0); 122 return std::auto_ptr<SECURITY_DESCRIPTOR>(0);
125 } 123 }
124 // Will be released later
125 PACL sacl = (PACL) new byte[saclSize];
Felix Dahlke 2014/07/16 14:40:03 I'd actually find malloc more intuitive here. byte
126 std::auto_ptr<SECURITY_DESCRIPTOR> absoluteDummySecurityDescriptorLow((SECUR ITY_DESCRIPTOR*) new byte[sdSize]);
127 daclSize = 0;
128 ownerSize = 0;
129 primaryGroupSize = 0;
130 BOOL res = MakeAbsoluteSD(dummySecurityDescriptorLow, absoluteDummySecurityD escriptorLow.get(), &sdSize, 0, &daclSize, sacl, &saclSize, 0, &ownerSize, 0, &p rimaryGroupSize);
131 if ((res == 0) || (absoluteDummySecurityDescriptorLow.get() == 0) || (saclSi ze == 0))
Felix Dahlke 2014/07/16 14:40:03 Redundant parentheses here as well. Also, !res wo
132 {
133 DWORD err = GetLastError();
Felix Dahlke 2014/07/16 14:40:03 Also unused.
134 return std::auto_ptr<SECURITY_DESCRIPTOR>(0);
135 }
136
137 // NOTE: This only references the acl, not copies it.
138 // DO NOT release the ACL before it's actually used
139 if (!SetSecurityDescriptorSacl(securityDescriptor.get(), TRUE, sacl, FALSE))
140 {
141 DWORD err = GetLastError();
142 return std::auto_ptr<SECURITY_DESCRIPTOR>(0);
126 } 143 }
127 144
128 return securityDescriptor; 145 return securityDescriptor;
129 } 146 }
130 } 147 }
131 148
132 // Releases the DACL structure in the provided security descriptor
133 void ReleaseDacl(PSECURITY_DESCRIPTOR securityDescriptor)
134 {
135 BOOL aclPresent = FALSE;
136 BOOL aclDefaulted = FALSE;
137 PACL acl;
138 GetSecurityDescriptorDacl(securityDescriptor, &aclPresent, &acl, &aclDefault ed);
139 if (aclPresent)
140 {
141 LocalFree(acl);
142 }
143 }
144 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); 149 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName();
145 150
146 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) 151 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType )
147 { 152 {
148 if (!hasType) 153 if (!hasType)
149 ReadBinary(currentType); 154 ReadBinary(currentType);
150 155
151 if (currentType != expectedType) 156 if (currentType != expectedType)
152 { 157 {
153 // Make sure we don't attempt to read the type again 158 // Make sure we don't attempt to read the type again
(...skipping 21 matching lines...) Expand all
175 Communication::PipeBusyError::PipeBusyError() 180 Communication::PipeBusyError::PipeBusyError()
176 : std::runtime_error("Timeout while trying to connect to a named pipe, pipe is busy") 181 : std::runtime_error("Timeout while trying to connect to a named pipe, pipe is busy")
177 { 182 {
178 } 183 }
179 184
180 Communication::PipeDisconnectedError::PipeDisconnectedError() 185 Communication::PipeDisconnectedError::PipeDisconnectedError()
181 : std::runtime_error("Pipe disconnected") 186 : std::runtime_error("Pipe disconnected")
182 { 187 {
183 } 188 }
184 189
190 void FreeAbsoluteSecurityDescriptor(SECURITY_DESCRIPTOR* securityDescriptor)
191 {
192 BOOL aclPresent = FALSE;
193 BOOL aclDefaulted = FALSE;
194 PACL acl = 0;
195 GetSecurityDescriptorDacl(securityDescriptor, &aclPresent, &acl, &aclDefaulted );
196 if (aclPresent)
197 {
198 LocalFree(acl);
199 }
200 aclPresent = FALSE;
201 aclDefaulted = false;
Felix Dahlke 2014/07/16 14:40:03 Should also be that Windows FALSE macro for consis
202 acl = 0;
203 GetSecurityDescriptorSacl(securityDescriptor, &aclPresent, &acl, &aclDefaulted );
204 if (aclPresent)
205 {
206 delete acl;
Felix Dahlke 2014/07/16 14:40:03 You need to use delete[], since it was allocated u
207 }
208 delete securityDescriptor;
209 }
210
185 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) 211 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode)
186 { 212 {
187 pipe = INVALID_HANDLE_VALUE; 213 pipe = INVALID_HANDLE_VALUE;
188 if (mode == MODE_CREATE) 214 if (mode == MODE_CREATE)
189 { 215 {
190 SECURITY_ATTRIBUTES securityAttributes = {}; 216 SECURITY_ATTRIBUTES securityAttributes = {};
191 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); 217 securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
192 securityAttributes.bInheritHandle = TRUE; 218 securityAttributes.bInheritHandle = TRUE;
193 219
194 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup 220 std::tr1::shared_ptr<SECURITY_DESCRIPTOR> sharedSecurityDescriptor; // Just to simplify cleanup
195
196 AutoHandle token; 221 AutoHandle token;
197 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token); 222 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, token);
198 223
199 if (IsWindowsVistaOrLater()) 224 if (IsWindowsVistaOrLater())
200 { 225 {
201 std::auto_ptr<SID> logonSid = GetLogonSid(token); 226 std::auto_ptr<SID> logonSid = GetLogonSid(token);
202 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acc ess to all AppContainers 227 // Create a SECURITY_DESCRIPTOR that has both Low Integrity and allows acc ess to all AppContainers
203 // This is needed since IE likes to jump out of Enhanced Protected Mode fo r specific pages (bing.com) 228 // This is needed since IE likes to jump out of Enhanced Protected Mode fo r specific pages (bing.com)
204
205 // ATTENTION: DACL in the returned securityDescriptor has to be manually r eleased by ReleaseDacl
206 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateSecurityDesc riptor(logonSid.get()); 229 std::auto_ptr<SECURITY_DESCRIPTOR> securityDescriptor = CreateSecurityDesc riptor(logonSid.get());
207 230
208 securityAttributes.lpSecurityDescriptor = securityDescriptor.release(); 231 securityAttributes.lpSecurityDescriptor = securityDescriptor.release();
209 sharedSecurityDescriptor.reset(static_cast<SECURITY_DESCRIPTOR*>(securityA ttributes.lpSecurityDescriptor)); 232 sharedSecurityDescriptor.reset(static_cast<SECURITY_DESCRIPTOR*>(securityA ttributes.lpSecurityDescriptor), FreeAbsoluteSecurityDescriptor);
210 } 233 }
211 pipe = CreateNamedPipeW(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 234 pipe = CreateNamedPipeW(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
212 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &securityAttributes); 235 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &securityAttributes);
213
214 if (IsWindowsVistaOrLater())
215 {
216 ReleaseDacl(securityAttributes.lpSecurityDescriptor);
217 }
218 } 236 }
219 else 237 else
220 { 238 {
221 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0); 239 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0);
222 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) 240 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY)
223 { 241 {
224 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) 242 if (!WaitNamedPipeW(pipeName.c_str(), 10000))
225 throw PipeBusyError(); 243 throw PipeBusyError();
226 244
227 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0); 245 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 return Communication::InputBuffer(stream.str()); 295 return Communication::InputBuffer(stream.str());
278 } 296 }
279 297
280 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) 298 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message)
281 { 299 {
282 DWORD bytesWritten; 300 DWORD bytesWritten;
283 std::string data = message.Get(); 301 std::string data = message.Get();
284 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) 302 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0))
285 throw std::runtime_error("Failed to write to pipe"); 303 throw std::runtime_error("Failed to write to pipe");
286 } 304 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld