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 | 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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |