 Issue 11756012:
  Enhanced Protected Mode support  (Closed)
    
  
    Issue 11756012:
  Enhanced Protected Mode support  (Closed) 
  | Left: | ||
| Right: | 
| OLD | NEW | 
|---|---|
| 1 #include <Windows.h> | 1 #include <Windows.h> | 
| 
Wladimir Palant
2013/09/17 07:53:48
From what I can tell, none of my comments in this
 | |
| 2 #include <Lmcons.h> | 2 #include <Lmcons.h> | 
| 3 #include <Sddl.h> | 3 #include <Sddl.h> | 
| 4 #include <aclapi.h> | |
| 5 #include <strsafe.h> | |
| 4 | 6 | 
| 5 #include "Communication.h" | 7 #include "Communication.h" | 
| 6 #include "Utils.h" | 8 #include "Utils.h" | 
| 7 | 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; | |
| 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) | |
| 39 { | |
| 40 if (ppsid == NULL) | |
| 41 return false; | |
| 42 | |
| 43 // Get required buffer size and allocate the TOKEN_GROUPS buffer. | |
| 44 DWORD dwLength = 0; | |
| 45 PTOKEN_GROUPS ptg = NULL; | |
| 46 if (!GetTokenInformation(hToken, TokenLogonSid, ptg, 0, &dwLength)) | |
| 47 { | |
| 48 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) | |
| 49 return false; | |
| 50 | |
| 51 ptg = (PTOKEN_GROUPS) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLeng th); | |
| 52 | |
| 53 if (ptg == NULL) | |
| 54 return false; | |
| 55 } | |
| 56 | |
| 57 // Get the token group information from the access token. | |
| 58 if (!GetTokenInformation(hToken, TokenLogonSid, ptg, dwLength, &dwLength) || ptg->GroupCount != 1) | |
| 59 { | |
| 60 HeapFree(GetProcessHeap(), 0, ptg); | |
| 61 return false; | |
| 62 } | |
| 63 | |
| 64 // Found the logon SID; make a copy of it. | |
| 65 dwLength = GetLengthSid(ptg->Groups[0].Sid); | |
| 66 *ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); | |
| 67 if (*ppsid == NULL) | |
| 68 { | |
| 69 HeapFree(GetProcessHeap(), 0, ptg); | |
| 70 return false; | |
| 71 } | |
| 72 if (!CopySid(dwLength, *ppsid, ptg->Groups[0].Sid)) | |
| 73 { | |
| 74 HeapFree(GetProcessHeap(), 0, ptg); | |
| 75 HeapFree(GetProcessHeap(), 0, *ppsid); | |
| 76 return false; | |
| 77 } | |
| 78 | |
| 79 HeapFree(GetProcessHeap(), 0, ptg); | |
| 80 return true; | |
| 81 } | |
| 82 | |
| 83 bool CreateObjectSecurityDescriptor(PSID pLogonSid, PSECURITY_DESCRIPTOR* ppSD ) | |
| 84 { | |
| 85 BOOL bSuccess = FALSE; | |
| 86 DWORD dwRes; | |
| 87 PSID pBrowserSID = NULL; | |
| 88 PACL pACL = NULL; | |
| 89 PSECURITY_DESCRIPTOR pSD = NULL; | |
| 90 EXPLICIT_ACCESS ea[2]; | |
| 91 SID_IDENTIFIER_AUTHORITY ApplicationAuthority = SECURITY_APP_PACKAGE_AUTHORI TY; | |
| 92 | |
| 93 ConvertStringSidToSid(Communication::browserSID.c_str(), &pBrowserSID); | |
| 94 | |
| 95 // Initialize an EXPLICIT_ACCESS structure for an ACE. | |
| 96 // The ACE will allow LogonSid generic all access | |
| 97 ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS)); | |
| 98 ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; | |
| 99 ea[0].grfAccessMode = SET_ACCESS; | |
| 100 ea[0].grfInheritance= NO_INHERITANCE; | |
| 101 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; | |
| 102 ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER; | |
| 103 ea[0].Trustee.ptstrName = (LPTSTR) pLogonSid; | |
| 104 | |
| 105 // Initialize an EXPLICIT_ACCESS structure for an ACE. | |
| 106 // The ACE will give the browser SID all permissions | |
| 107 ea[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; | |
| 108 ea[1].grfAccessMode = SET_ACCESS; | |
| 109 ea[1].grfInheritance= NO_INHERITANCE; | |
| 110 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; | |
| 111 ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; | |
| 112 ea[1].Trustee.ptstrName = (LPTSTR) pBrowserSID; | |
| 113 | |
| 114 // Create a new ACL that contains the new ACEs. | |
| 115 dwRes = SetEntriesInAcl(2, ea, NULL, &pACL); | |
| 116 if (ERROR_SUCCESS != dwRes) | |
| 117 { | |
| 118 FreeSid(pBrowserSID); | |
| 119 return false; | |
| 120 } | |
| 121 | |
| 122 // Initialize a security descriptor. | |
| 123 pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH ); | |
| 124 if (NULL == pSD) | |
| 125 { | |
| 126 FreeSid(pBrowserSID); | |
| 127 LocalFree(pACL); | |
| 128 return false;; | |
| 129 } | |
| 130 | |
| 131 if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) | |
| 132 { | |
| 133 FreeSid(pBrowserSID); | |
| 134 LocalFree(pACL); | |
| 135 LocalFree((LPVOID)pSD); | |
| 136 return false; | |
| 137 } | |
| 138 | |
| 139 // Add the ACL to the security descriptor. | |
| 140 if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) // not a default D ACL | |
| 141 { | |
| 142 FreeSid(pBrowserSID); | |
| 143 LocalFree(pACL); | |
| 144 LocalFree((LPVOID)pSD); | |
| 145 return false; | |
| 146 } | |
| 147 | |
| 148 *ppSD = pSD; | |
| 149 pSD = NULL; | |
| 150 | |
| 151 if (pBrowserSID) | |
| 152 FreeSid(pBrowserSID); | |
| 153 if (pACL) | |
| 154 LocalFree(pACL); | |
| 155 | |
| 156 return true; | |
| 157 } | |
| 158 | |
| 159 | |
| 28 } | 160 } | 
| 29 | 161 | 
| 30 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); | 162 const std::wstring Communication::pipeName = L"\\\\.\\pipe\\adblockplusengine_" + GetUserName(); | 
| 31 | 163 | 
| 32 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) | 164 void Communication::InputBuffer::CheckType(Communication::ValueType expectedType ) | 
| 33 { | 165 { | 
| 34 if (!hasType) | 166 if (!hasType) | 
| 35 ReadBinary(currentType); | 167 ReadBinary(currentType); | 
| 36 | 168 | 
| 37 if (currentType != expectedType) | 169 if (currentType != expectedType) | 
| (...skipping 22 matching lines...) Expand all Loading... | |
| 60 | 192 | 
| 61 Communication::PipeBusyError::PipeBusyError() | 193 Communication::PipeBusyError::PipeBusyError() | 
| 62 : std::runtime_error("Timeout while trying to connect to a named pipe, pipe is busy") | 194 : std::runtime_error("Timeout while trying to connect to a named pipe, pipe is busy") | 
| 63 { | 195 { | 
| 64 } | 196 } | 
| 65 | 197 | 
| 66 Communication::PipeDisconnectedError::PipeDisconnectedError() | 198 Communication::PipeDisconnectedError::PipeDisconnectedError() | 
| 67 : std::runtime_error("Pipe disconnected") | 199 : std::runtime_error("Pipe disconnected") | 
| 68 { | 200 { | 
| 69 } | 201 } | 
| 70 | |
| 71 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) | 202 Communication::Pipe::Pipe(const std::wstring& pipeName, Communication::Pipe::Mod e mode) | 
| 
Wladimir Palant
2013/09/17 07:53:48
Not addressed: the empty line before this function
 | |
| 72 { | 203 { | 
| 73 pipe = INVALID_HANDLE_VALUE; | 204 pipe = INVALID_HANDLE_VALUE; | 
| 74 if (mode == MODE_CREATE) | 205 if (mode == MODE_CREATE) | 
| 75 { | 206 { | 
| 76 SECURITY_ATTRIBUTES sa; | 207 SECURITY_ATTRIBUTES sa; | 
| 77 memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); | 208 memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); | 
| 78 sa.nLength = sizeof(SECURITY_ATTRIBUTES); | 209 sa.nLength = sizeof(SECURITY_ATTRIBUTES); | 
| 79 | 210 | 
| 80 PSECURITY_DESCRIPTOR securitydescriptor; | 211 HANDLE hToken = NULL; | 
| 81 if (IsWindowsVistaOrLater()) | 212 OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken); | 
| 213 | |
| 214 if (browserSID.empty()) | |
| 82 { | 215 { | 
| 83 // Low mandatory label. See http://msdn.microsoft.com/en-us/library/bb6259 58.aspx | 216 if (IsWindowsVistaOrLater()) | 
| 84 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; | 217 { | 
| 85 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, S DDL_REVISION_1, &securitydescriptor, 0); | 218 // Low mandatory label. See http://msdn.microsoft.com/en-us/library/bb62 5958.aspx | 
| 86 sa.lpSecurityDescriptor = securitydescriptor; | 219 LPCWSTR accessControlEntry = L"S:(ML;;NW;;;LW)"; | 
| 220 ConvertStringSecurityDescriptorToSecurityDescriptorW(accessControlEntry, SDDL_REVISION_1, &securitydescriptor, 0); | |
| 221 sa.lpSecurityDescriptor = securitydescriptor; | |
| 222 } | |
| 223 | |
| 224 sa.bInheritHandle = TRUE; | |
| 87 } | 225 } | 
| 88 | 226 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 { | 227 { | 
| 95 LocalFree(securitydescriptor); | 228 PSID pLogonSid = NULL; | 
| 229 //Allowing LogonSid and IE's appcontainer. | |
| 230 if (GetLogonSid(hToken, &pLogonSid) && CreateObjectSecurityDescriptor(pLog onSid, &securitydescriptor) ) | |
| 231 { | |
| 232 sa.nLength = sizeof(SECURITY_ATTRIBUTES); | |
| 233 sa.bInheritHandle = TRUE; | |
| 234 sa.lpSecurityDescriptor = securitydescriptor; | |
| 235 } | |
| 96 } | 236 } | 
| 97 } | 237 pipe = CreateNamedPipe(pipeName.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESS AGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, | 
| 238 PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &sa); | |
| 239 } | |
| 98 else | 240 else | 
| 99 { | 241 { | 
| 100 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPE N_EXISTING, 0, 0); | 242 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) | 243 if (pipe == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) | 
| 102 { | 244 { | 
| 103 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) | 245 if (!WaitNamedPipeW(pipeName.c_str(), 10000)) | 
| 104 throw PipeBusyError(); | 246 throw PipeBusyError(); | 
| 105 | 247 | 
| 106 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0); | 248 pipe = CreateFileW(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, O PEN_EXISTING, 0, 0); | 
| 107 } | 249 } | 
| 108 } | 250 } | 
| 109 | 251 | 
| 110 if (pipe == INVALID_HANDLE_VALUE) | 252 if (pipe == INVALID_HANDLE_VALUE) | 
| 111 throw PipeConnectionError(); | 253 throw PipeConnectionError(); | 
| 112 | 254 | 
| 113 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; | 255 DWORD pipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; | 
| 114 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0)) | 256 if (!SetNamedPipeHandleState(pipe, &pipeMode, 0, 0)) | 
| 115 throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastE rror()); | 257 throw std::runtime_error("SetNamedPipeHandleState failed: error " + GetLastE rror()); | 
| 116 | 258 | 
| 117 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0)) | 259 if (mode == MODE_CREATE && !ConnectNamedPipe(pipe, 0)) | 
| 118 throw std::runtime_error("Client failed to connect: error " + GetLastError() ); | 260 throw std::runtime_error("Client failed to connect: error " + GetLastError() ); | 
| 119 } | 261 } | 
| 120 | 262 | 
| 121 Communication::Pipe::~Pipe() | 263 Communication::Pipe::~Pipe() | 
| 122 { | 264 { | 
| 123 CloseHandle(pipe); | 265 CloseHandle(pipe); | 
| 266 if (securitydescriptor) | |
| 267 LocalFree(securitydescriptor); | |
| 268 | |
| 124 } | 269 } | 
| 125 | 270 | 
| 126 Communication::InputBuffer Communication::Pipe::ReadMessage() | 271 Communication::InputBuffer Communication::Pipe::ReadMessage() | 
| 127 { | 272 { | 
| 128 std::stringstream stream; | 273 std::stringstream stream; | 
| 129 std::auto_ptr<char> buffer(new char[bufferSize]); | 274 std::auto_ptr<char> buffer(new char[bufferSize]); | 
| 130 bool doneReading = false; | 275 bool doneReading = false; | 
| 131 while (!doneReading) | 276 while (!doneReading) | 
| 132 { | 277 { | 
| 133 DWORD bytesRead; | 278 DWORD bytesRead; | 
| (...skipping 19 matching lines...) Expand all Loading... | |
| 153 return Communication::InputBuffer(stream.str()); | 298 return Communication::InputBuffer(stream.str()); | 
| 154 } | 299 } | 
| 155 | 300 | 
| 156 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) | 301 void Communication::Pipe::WriteMessage(Communication::OutputBuffer& message) | 
| 157 { | 302 { | 
| 158 DWORD bytesWritten; | 303 DWORD bytesWritten; | 
| 159 std::string data = message.Get(); | 304 std::string data = message.Get(); | 
| 160 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) | 305 if (!WriteFile(pipe, data.c_str(), static_cast<DWORD>(data.length()), &bytesWr itten, 0)) | 
| 161 throw std::runtime_error("Failed to write to pipe"); | 306 throw std::runtime_error("Failed to write to pipe"); | 
| 162 } | 307 } | 
| OLD | NEW |