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: Created May 13, 2014, 12:21 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 | src/shared/Utils.h » ('j') | src/shared/Utils.cpp » ('J')
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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | src/shared/Utils.h » ('j') | src/shared/Utils.cpp » ('J')

Powered by Google App Engine
This is Rietveld