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

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

Issue 11756012: Enhanced Protected Mode support (Closed)
Patch Set: Created Sept. 15, 2013, 1 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« src/shared/Communication.h ('K') | « src/shared/Communication.h ('k') | 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 5
5 #include "Communication.h" 6 #include "Communication.h"
6 #include "Utils.h" 7 #include "Utils.h"
8 #include <strsafe.h>
Wladimir Palant 2013/09/16 13:45:07 Please move that up, to the built-in include files
9
10 #ifndef SECURITY_APP_PACKAGE_AUTHORITY
11 #define SECURITY_APP_PACKAGE_AUTHORITY {0,0,0,0,0,15}
12 #endif
13
14 std::wstring Communication::browserSID;
7 15
8 namespace 16 namespace
9 { 17 {
10 const int bufferSize = 1024; 18 const int bufferSize = 1024;
11 19
12 std::string AppendErrorCode(const std::string& message) 20 std::string AppendErrorCode(const std::string& message)
13 { 21 {
14 std::stringstream stream; 22 std::stringstream stream;
15 stream << message << " (Error code: " << GetLastError() << ")"; 23 stream << message << " (Error code: " << GetLastError() << ")";
16 return stream.str(); 24 return stream.str();
17 } 25 }
18 26
19 std::wstring GetUserName() 27 std::wstring GetUserName()
20 { 28 {
21 const DWORD maxLength = UNLEN + 1; 29 const DWORD maxLength = UNLEN + 1;
22 std::auto_ptr<wchar_t> buffer(new wchar_t[maxLength]); 30 std::auto_ptr<wchar_t> buffer(new wchar_t[maxLength]);
23 DWORD length = maxLength; 31 DWORD length = maxLength;
24 if (!::GetUserNameW(buffer.get(), &length)) 32 if (!::GetUserNameW(buffer.get(), &length))
25 throw std::runtime_error(AppendErrorCode("Failed to get the current user's name")); 33 throw std::runtime_error(AppendErrorCode("Failed to get the current user's name"));
26 return std::wstring(buffer.get(), length); 34 return std::wstring(buffer.get(), length);
27 } 35 }
36
37 // See http://msdn.microsoft.com/en-us/library/windows/desktop/hh448493(v=vs.8 5).aspx
38 bool GetLogonSid (HANDLE hToken, PSID *ppsid)
Felix Dahlke 2013/09/16 16:30:12 Nit: No space after GetLogonSid?
39 {
40 DWORD dwLength = 0;
41 PTOKEN_GROUPS ptg = NULL;
42
43 // Verify the parameter passed in is not NULL.
Felix Dahlke 2013/09/16 16:30:12 I do think this is kinda obvious from the conditio
44 if (NULL == ppsid)
Felix Dahlke 2013/09/16 16:30:12 We normally don't use Yoda conditions :D But it's
45 return false;
46
47 // Get required buffer size and allocate the TOKEN_GROUPS buffer.
48 if (!GetTokenInformation(hToken, TokenLogonSid, (LPVOID) ptg, 0, &dwLength))
Felix Dahlke 2013/09/16 16:30:12 This code looks very similar to what's in AdblockP
49 {
50 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
51 return false;
52
53 ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLengt h);
54
55 if (ptg == NULL)
56 return false;
57 }
58
59 // Get the token group information from the access token.
60 if (!GetTokenInformation(hToken, TokenLogonSid, (LPVOID) ptg, dwLength, &dwL ength) || ptg->GroupCount != 1)
61 {
62 HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
63 return false;
64 }
65
66 // Found the logon SID; make a copy of it.
67 dwLength = GetLengthSid(ptg->Groups[0].Sid);
68 *ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
69 if (*ppsid == NULL)
70 {
71 HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
72 return false;
73 }
74 if (!CopySid(dwLength, *ppsid, ptg->Groups[0].Sid))
75 {
76 HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
77 HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
78 return false;
79 }
80
81 HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
82 return true;
83 }
84
85 bool CreateObjectSecurityDescriptor(PSID pLogonSid, PSECURITY_DESCRIPTOR* ppSD )
86 {
87 BOOL bSuccess = FALSE;
Felix Dahlke 2013/09/16 16:30:12 I'd rather have these declarations closer to their
88 DWORD dwRes;
89 PSID pBrowserSID = NULL;
90 PACL pACL = NULL;
91 PSECURITY_DESCRIPTOR pSD = NULL;
92 EXPLICIT_ACCESS ea[2];
93 SID_IDENTIFIER_AUTHORITY ApplicationAuthority = SECURITY_APP_PACKAGE_AUTHORI TY;
94
95 ConvertStringSidToSid(Communication::browserSID.c_str(), &pBrowserSID);
96
97 // Initialize an EXPLICIT_ACCESS structure for an ACE.
98 // The ACE will allow LogonSid generic all access
99 ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));
100 ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
101 ea[0].grfAccessMode = SET_ACCESS;
102 ea[0].grfInheritance= NO_INHERITANCE;
103 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
104 ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER;
105 ea[0].Trustee.ptstrName = (LPTSTR) pLogonSid;
106
107 // Initialize an EXPLICIT_ACCESS structure for an ACE.
108 // The ACE will give the browser SID all permissions
109 ea[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
110 ea[1].grfAccessMode = SET_ACCESS;
111 ea[1].grfInheritance= NO_INHERITANCE;
112 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
113 ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
114 ea[1].Trustee.ptstrName = (LPTSTR) pBrowserSID;
115
116 // Create a new ACL that contains the new ACEs.
117 dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);
118 if (ERROR_SUCCESS != dwRes)
119 {
120 FreeSid(pBrowserSID);
121 return false;
122 }
123
124 // Initialize a security descriptor.
125 pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH );
126 if (NULL == pSD)
127 {
128 FreeSid(pBrowserSID);
129 LocalFree(pACL);
130 return false;;
131 }
132
133 if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
134 {
135 FreeSid(pBrowserSID);
136 LocalFree(pACL);
137 LocalFree((LPVOID)pSD);
138 return false;
139 }
140
141 // Add the ACL to the security descriptor.
142 if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) // not a default D ACL
143 {
144 FreeSid(pBrowserSID);
145 LocalFree(pACL);
146 LocalFree((LPVOID)pSD);
147 return false;
148 }
149
150 *ppSD = pSD;
151 pSD = NULL;
152
153 if (pBrowserSID)
154 FreeSid(pBrowserSID);
155 if (pACL)
156 LocalFree(pACL);
157
158 return true;
159 }
160
161
28 } 162 }
29 163
30 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); 164 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName();
31 165
32 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) 166 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType )
33 { 167 {
34 if (!hasType) 168 if (!hasType)
35 ReadBinary(currentType); 169 ReadBinary(currentType);
36 170
37 if (currentType != expectedType) 171 if (currentType != expectedType)
(...skipping 22 matching lines...) Expand all
60 194
61 Communication::PipeBusyError::PipeBusyError() 195 Communication::PipeBusyError::PipeBusyError()
62 : std::runtime_error("Timeout while trying to connect to a named pipe, pipe is busy") 196 : std::runtime_error("Timeout while trying to connect to a named pipe, pipe is busy")
63 { 197 {
64 } 198 }
65 199
66 Communication::PipeDisconnectedError::PipeDisconnectedError() 200 Communication::PipeDisconnectedError::PipeDisconnectedError()
67 : std::runtime_error("Pipe disconnected") 201 : std::runtime_error("Pipe disconnected")
68 { 202 {
69 } 203 }
70
71 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) 204 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode)
Wladimir Palant 2013/09/16 13:45:07 Nit: Please keep an empty line before this one.
72 { 205 {
73 pipe = INVALID_HANDLE_VALUE; 206 pipe = INVALID_HANDLE_VALUE;
74 if (mode == MODE_CREATE) 207 if (mode == MODE_CREATE)
75 { 208 {
76 SECURITY_ATTRIBUTES sa; 209 SECURITY_ATTRIBUTES sa;
77 memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); 210 memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
78 sa.nLength = sizeof(SECURITY_ATTRIBUTES); 211 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
79 212
80 PSECURITY_DESCRIPTOR securitydescriptor; 213 HANDLE hToken = NULL;
81 if (IsWindowsVistaOrLater()) 214 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken);
215
216 if (browserSID.empty())
82 { 217 {
83 // Low mandatory label. See http://msdn.microsoft.com/en-us/library/bb6259 58.aspx 218 if (IsWindowsVistaOrLater())
84 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; 219 {
85 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, S DDL_REVISION_1, &securitydescriptor, 0); 220 // Low mandatory label. See http://msdn.microsoft.com/en-us/library/bb62 5958.aspx
86 sa.lpSecurityDescriptor = securitydescriptor; 221 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)";
222 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDDL_REVISION_1, &securitydescriptor, 0);
223 sa.lpSecurityDescriptor = securitydescriptor;
224 }
225
226 sa.bInheritHandle = TRUE;
87 } 227 }
88 228 else // IE is in AppContainer
89 sa.bInheritHandle = TRUE;
90
91 pipe = CreateNamedPipeW (pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MES SAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
92 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSi ze, 0, &sa);
93 if (IsWindowsVistaOrLater() && securitydescriptor)
94 { 229 {
95 LocalFree(securitydescriptor); 230 PSID pLogonSid = NULL;
231 //Allowing LogonSid and IE's appcontainer.
232 if (GetLogonSid(hToken, &pLogonSid) && CreateObjectSecurityDescriptor(pLog onSid, &securitydescriptor) )
Wladimir Palant 2013/09/16 13:45:07 Why do we need to allow the logon sid? Is it for t
Oleksandr 2013/09/17 08:27:19 Our plugin is unable to access the named pipe if w
233 {
234 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
235 sa.bInheritHandle = TRUE;
Wladimir Palant 2013/09/16 13:45:07 I think that we still want to set this in any case
236 sa.lpSecurityDescriptor = securitydescriptor;
237 }
96 } 238 }
97 } 239 pipe = CreateNamedPipe(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESS AGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
Wladimir Palant 2013/09/16 13:45:07 Please use CreateNamedPipeW explicitly, as we had
240 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &sa);
241 }
Wladimir Palant 2013/09/16 13:45:07 Bad indentation?
98 else 242 else
99 { 243 {
100 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0); 244 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0);
101 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) 245 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY)
102 { 246 {
103 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) 247 if (!WaitNamedPipeW(pipeName.c_str(), 10000))
104 throw PipeBusyError(); 248 throw PipeBusyError();
105 249
106 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0); 250 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0);
107 } 251 }
108 } 252 }
109 253
110 if (pipe == INVALID_HANDLE_VALUE) 254 if (pipe == INVALID_HANDLE_VALUE)
111 throw PipeConnectionError(); 255 throw PipeConnectionError();
112 256
113 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; 257 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
114 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0)) 258 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0))
115 throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastE rror()); 259 throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastE rror());
116 260
117 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0)) 261 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0))
118 throw std::runtime_error("Client failed to connect: error " + GetLastError() ); 262 throw std::runtime_error("Client failed to connect: error " + GetLastError() );
119 } 263 }
120 264
121 Communication::Pipe::~Pipe() 265 Communication::Pipe::~Pipe()
122 { 266 {
123 CloseHandle(pipe); 267 CloseHandle(pipe);
268 if (securitydescriptor)
269 LocalFree(securitydescriptor);
270
124 } 271 }
125 272
126 Communication::InputBuffer Communication::Pipe::ReadMessage() 273 Communication::InputBuffer Communication::Pipe::ReadMessage()
127 { 274 {
128 std::stringstream stream; 275 std::stringstream stream;
129 std::auto_ptr<char> buffer(new char[bufferSize]); 276 std::auto_ptr<char> buffer(new char[bufferSize]);
130 bool doneReading = false; 277 bool doneReading = false;
131 while (!doneReading) 278 while (!doneReading)
132 { 279 {
133 DWORD bytesRead; 280 DWORD bytesRead;
(...skipping 19 matching lines...) Expand all
153 return Communication::InputBuffer(stream.str()); 300 return Communication::InputBuffer(stream.str());
154 } 301 }
155 302
156 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) 303 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message)
157 { 304 {
158 DWORD bytesWritten; 305 DWORD bytesWritten;
159 std::string data = message.Get(); 306 std::string data = message.Get();
160 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) 307 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0))
161 throw std::runtime_error("Failed to write to pipe"); 308 throw std::runtime_error("Failed to write to pipe");
162 } 309 }
OLDNEW
« src/shared/Communication.h ('K') | « src/shared/Communication.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld