Changeset 96599 in vbox
- Timestamp:
- Sep 5, 2022 2:05:21 AM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 153476
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/win/localipc-win.cpp
r96505 r96599 43 43 *********************************************************************************************************************************/ 44 44 #define LOG_GROUP RTLOGGROUP_LOCALIPC 45 #ifdef _WIN32_WINNT 46 # if _WIN32_WINNT < 0x0500 47 # undef _WIN32_WINNT 48 # define _WIN32_WINNT 0x0500 /* For ConvertStringSecurityDescriptorToSecurityDescriptor. */ 49 # endif 50 #endif 51 #define UNICODE /* For the SDDL_ strings. */ 52 #include <iprt/nt/nt-and-windows.h> /* Need NtCancelIoFile */ 45 #include <iprt/nt/nt-and-windows.h> /* Need NtCancelIoFile and a few Rtl functions. */ 53 46 #include <sddl.h> 47 #include <aclapi.h> 54 48 55 49 #include "internal/iprt.h" … … 80 74 /** Pipe prefix string. */ 81 75 #define RTLOCALIPC_WIN_PREFIX L"\\\\.\\pipe\\IPRT-" 82 83 /** DACL for block all network access and local users other than the creator/owner.84 *85 * ACE format: (ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid)86 *87 * Note! FILE_GENERIC_WRITE (SDDL_FILE_WRITE) is evil here because it includes88 * the FILE_CREATE_PIPE_INSTANCE(=FILE_APPEND_DATA) flag. Thus the hardcoded89 * value 0x0012019b in the client ACE. The server-side still needs90 * setting FILE_CREATE_PIPE_INSTANCE although.91 * It expands to:92 * 0x00000001 - FILE_READ_DATA93 * 0x00000008 - FILE_READ_EA94 * 0x00000080 - FILE_READ_ATTRIBUTES95 * 0x00020000 - READ_CONTROL96 * 0x00100000 - SYNCHRONIZE97 * 0x00000002 - FILE_WRITE_DATA98 * 0x00000010 - FILE_WRITE_EA99 * 0x00000100 - FILE_WRITE_ATTRIBUTES100 * = 0x0012019b (client)101 * + (only for server):102 * 0x00000004 - FILE_CREATE_PIPE_INSTANCE103 * = 0x0012019f104 *105 * @todo Triple check this!106 * @todo EVERYONE -> AUTHENTICATED USERS or something more appropriate?107 * @todo Have trouble allowing the owner FILE_CREATE_PIPE_INSTANCE access, so for now I'm hacking108 * it just to get progress - the service runs as local system.109 * The CREATOR OWNER and PERSONAL SELF works (the former is only involved in inheriting110 * it seems, which is why it won't work. The latter I've no idea about. Perhaps the solution111 * is to go the annoying route of OpenProcessToken, QueryTokenInformation,112 * ConvertSidToStringSid and then use the result... Suggestions are very welcome113 */114 #define RTLOCALIPC_WIN_SDDL_BASE \115 SDDL_DACL SDDL_DELIMINATOR \116 SDDL_ACE_BEGIN SDDL_ACCESS_DENIED L";;" SDDL_GENERIC_ALL L";;;" SDDL_NETWORK SDDL_ACE_END \117 SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";;" SDDL_FILE_ALL L";;;" SDDL_LOCAL_SYSTEM SDDL_ACE_END118 119 #define RTLOCALIPC_WIN_SDDL_SERVER \120 RTLOCALIPC_WIN_SDDL_BASE \121 SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";;" L"0x0012019f" L";;;" SDDL_EVERYONE SDDL_ACE_END122 123 #define RTLOCALIPC_WIN_SDDL_CLIENT \124 RTLOCALIPC_WIN_SDDL_BASE \125 SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";;" L"0x0012019b" L";;;" SDDL_EVERYONE SDDL_ACE_END126 127 // SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";;" SDDL_GENERIC_ALL L";;;" SDDL_PERSONAL_SELF SDDL_ACE_END \128 // SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";CIOI;" SDDL_GENERIC_ALL L";;;" SDDL_CREATOR_OWNER SDDL_ACE_END129 // SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";;" L"0x0012019b" L";;;" SDDL_EVERYONE SDDL_ACE_END130 // SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";;" SDDL_FILE_ALL L";;;" SDDL_LOCAL_SYSTEM SDDL_ACE_END131 76 132 77 … … 220 165 221 166 222 /********************************************************************************************************************************* 223 * Global Variables * 224 *********************************************************************************************************************************/ 225 static bool volatile g_fResolvedApis = false; 226 /** advapi32.dll API ConvertStringSecurityDescriptorToSecurityDescriptorW. */ 227 static decltype(ConvertStringSecurityDescriptorToSecurityDescriptorW) *g_pfnSSDLToSecDescW = NULL; 167 /** 168 * DACL for block all network access and local users other than the creator/owner. 169 * 170 * ACE format: (ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid) 171 * 172 * Note! FILE_GENERIC_WRITE (SDDL_FILE_WRITE) is evil here because it includes 173 * the FILE_CREATE_PIPE_INSTANCE(=FILE_APPEND_DATA) flag. Thus the hardcoded 174 * value 0x0012019b in the client ACE. The server-side still needs 175 * setting FILE_CREATE_PIPE_INSTANCE although. 176 * It expands to: 177 * 0x00000001 - FILE_READ_DATA 178 * 0x00000008 - FILE_READ_EA 179 * 0x00000080 - FILE_READ_ATTRIBUTES 180 * 0x00020000 - READ_CONTROL 181 * 0x00100000 - SYNCHRONIZE 182 * 0x00000002 - FILE_WRITE_DATA 183 * 0x00000010 - FILE_WRITE_EA 184 * 0x00000100 - FILE_WRITE_ATTRIBUTES 185 * = 0x0012019b (client) 186 * + (only for server): 187 * 0x00000004 - FILE_CREATE_PIPE_INSTANCE 188 * = 0x0012019f 189 * 190 * @todo Triple check this! 191 * @todo EVERYONE -> AUTHENTICATED USERS or something more appropriate? 192 * @todo Have trouble allowing the owner FILE_CREATE_PIPE_INSTANCE access, so for now I'm hacking 193 * it just to get progress - the service runs as local system. 194 * The CREATOR OWNER and PERSONAL SELF works (the former is only involved in inheriting 195 * it seems, which is why it won't work. The latter I've no idea about. Perhaps the solution 196 * is to go the annoying route of OpenProcessToken, QueryTokenInformation, 197 * ConvertSidToStringSid and then use the result... Suggestions are very welcome 198 */ 199 #define RTLOCALIPC_WIN_SDDL_BASE \ 200 SDDL_DACL SDDL_DELIMINATOR \ 201 SDDL_ACE_BEGIN SDDL_ACCESS_DENIED L";;" SDDL_GENERIC_ALL L";;;" SDDL_NETWORK SDDL_ACE_END \ 202 SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";;" SDDL_FILE_ALL L";;;" SDDL_LOCAL_SYSTEM SDDL_ACE_END 203 #define RTLOCALIPC_WIN_SDDL_SERVER \ 204 RTLOCALIPC_WIN_SDDL_BASE \ 205 SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";;" L"0x0012019f" L";;;" SDDL_EVERYONE SDDL_ACE_END 206 #define RTLOCALIPC_WIN_SDDL_CLIENT \ 207 RTLOCALIPC_WIN_SDDL_BASE \ 208 SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED L";;" L"0x0012019b" L";;;" SDDL_EVERYONE SDDL_ACE_END 209 static NTSTATUS rtLocalIpcBuildDacl(PACL pDacl, bool fServer) 210 { 211 static SID_IDENTIFIER_AUTHORITY s_NtAuth = SECURITY_NT_AUTHORITY; 212 static SID_IDENTIFIER_AUTHORITY s_WorldAuth = SECURITY_WORLD_SID_AUTHORITY; 213 union 214 { 215 SID Sid; 216 uint8_t abPadding[SECURITY_MAX_SID_SIZE]; 217 } Network, LocalSystem, Everyone; 218 219 220 /* 1. SDDL_ACCESS_DENIED L";;" SDDL_GENERIC_ALL L";;;" SDDL_NETWORK */ 221 NTSTATUS rcNt = RtlInitializeSid(&Network.Sid, &s_NtAuth, 1); 222 AssertReturn(NT_SUCCESS(rcNt), rcNt); 223 *RtlSubAuthoritySid(&Network.Sid, 0) = SECURITY_NETWORK_RID; 224 225 rcNt = RtlAddAccessDeniedAce(pDacl, ACL_REVISION, GENERIC_ALL, &Network.Sid); 226 AssertReturn(NT_SUCCESS(rcNt), rcNt); 227 228 /* 2. SDDL_ACCESS_ALLOWED L";;" SDDL_FILE_ALL L";;;" SDDL_LOCAL_SYSTEM */ 229 rcNt = RtlInitializeSid(&LocalSystem.Sid, &s_NtAuth, 1); 230 AssertReturn(NT_SUCCESS(rcNt), rcNt); 231 *RtlSubAuthoritySid(&LocalSystem.Sid, 0) = SECURITY_LOCAL_SYSTEM_RID; 232 233 rcNt = RtlAddAccessAllowedAce(pDacl, ACL_REVISION, FILE_ALL_ACCESS, &Network.Sid); 234 AssertReturn(NT_SUCCESS(rcNt), rcNt); 235 236 237 /* 3. server: SDDL_ACCESS_ALLOWED L";;" L"0x0012019f" L";;;" SDDL_EVERYONE 238 client: SDDL_ACCESS_ALLOWED L";;" L"0x0012019b" L";;;" SDDL_EVERYONE */ 239 rcNt = RtlInitializeSid(&Everyone.Sid, &s_NtAuth, 1); 240 AssertReturn(NT_SUCCESS(rcNt), rcNt); 241 *RtlSubAuthoritySid(&Everyone.Sid, 0) = SECURITY_WORLD_RID; 242 243 DWORD const fAccess = FILE_READ_DATA /* 0x00000001 */ 244 | FILE_WRITE_DATA /* 0x00000002 */ 245 | FILE_CREATE_PIPE_INSTANCE * fServer /* 0x00000004 */ 246 | FILE_READ_EA /* 0x00000008 */ 247 | FILE_WRITE_EA /* 0x00000010 */ 248 | FILE_READ_ATTRIBUTES /* 0x00000080 */ 249 | FILE_WRITE_ATTRIBUTES /* 0x00000100 */ 250 | READ_CONTROL /* 0x00020000 */ 251 | SYNCHRONIZE; /* 0x00100000*/ 252 Assert(fAccess == (fServer ? 0x0012019fU : 0x0012019bU)); 253 254 rcNt = RtlAddAccessAllowedAce(pDacl, ACL_REVISION, fAccess, &Network.Sid); 255 AssertReturn(NT_SUCCESS(rcNt), rcNt); 256 257 return true; 258 } 228 259 229 260 … … 238 269 static int rtLocalIpcServerWinAllocSecurityDescriptor(PSECURITY_DESCRIPTOR *ppDesc, bool fServer) 239 270 { 271 int rc; 272 PSECURITY_DESCRIPTOR pSecDesc = NULL; 273 274 #if 0 240 275 /* 241 276 * Resolve the API the first time around. 242 277 */ 243 if (!g_fResolvedApis) 244 { 245 g_pfnSSDLToSecDescW = (decltype(g_pfnSSDLToSecDescW))RTLdrGetSystemSymbol("advapi32.dll", "ConvertStringSecurityDescriptorToSecurityDescriptorW"); 278 static bool volatile s_fResolvedApis = false; 279 /** advapi32.dll API ConvertStringSecurityDescriptorToSecurityDescriptorW. */ 280 static decltype(ConvertStringSecurityDescriptorToSecurityDescriptorW) *s_pfnSSDLToSecDescW = NULL; 281 282 if (!s_fResolvedApis) 283 { 284 s_pfnSSDLToSecDescW 285 = (decltype(s_pfnSSDLToSecDescW))RTLdrGetSystemSymbol("advapi32.dll", 286 "ConvertStringSecurityDescriptorToSecurityDescriptorW"); 246 287 ASMCompilerBarrier(); 247 g_fResolvedApis = true; 248 } 249 250 int rc; 251 PSECURITY_DESCRIPTOR pSecDesc = NULL; 252 if (g_pfnSSDLToSecDescW) 288 s_fResolvedApis = true; 289 } 290 if (s_pfnSSDLToSecDescW) 253 291 { 254 292 /* … … 258 296 * users from screwing around. 259 297 */ 260 PCRTUTF16 pwszSDDL = fServer ? RTLOCALIPC_WIN_SDDL_SERVER : RTLOCALIPC_WIN_SDDL_CLIENT; 261 if (g_pfnSSDLToSecDescW(pwszSDDL, SDDL_REVISION_1, &pSecDesc, NULL)) 262 { 298 PCRTUTF16 pwszSDDL = fServer ? RTLOCALIPC_WIN_SDDL_SERVER : RTLOCALIPC_WIN_SDDL_CLIENT; 299 ULONG cbSecDesc = 0; 300 SetLastError(0); 301 if (s_pfnSSDLToSecDescW(pwszSDDL, SDDL_REVISION_1, &pSecDesc, &cbSecDesc)) 302 { 303 DWORD dwErr = GetLastError(); RT_NOREF(dwErr); 263 304 AssertPtr(pSecDesc); 264 305 *ppDesc = pSecDesc; … … 269 310 } 270 311 else 271 { 272 /* Windows OSes < W2K SP2 not supported for now, bail out. */ 273 /** @todo Implement me! */ 274 rc = VERR_NOT_SUPPORTED; 312 #endif 313 { 314 /* 315 * Manually construct the descriptor. 316 * 317 * This is a bit crude. The 8KB is probably 50+ times more than what we need. 318 */ 319 uint32_t const cbAlloc = SECURITY_DESCRIPTOR_MIN_LENGTH * 2 + _8K; 320 pSecDesc = LocalAlloc(LMEM_FIXED, cbAlloc); 321 if (!pSecDesc) 322 return VERR_NO_MEMORY; 323 RT_BZERO(pSecDesc, cbAlloc); 324 325 uint32_t const cbDacl = cbAlloc - SECURITY_DESCRIPTOR_MIN_LENGTH * 2; 326 PACL const pDacl = (PACL)((uint8_t *)pSecDesc + SECURITY_DESCRIPTOR_MIN_LENGTH * 2); 327 328 if ( InitializeSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION) 329 && InitializeAcl(pDacl, cbDacl, ACL_REVISION)) 330 { 331 if (rtLocalIpcBuildDacl(pDacl, fServer)) 332 { 333 *ppDesc = pSecDesc; 334 return VINF_SUCCESS; 335 } 336 rc = VERR_GENERAL_FAILURE; 337 } 338 else 339 rc = RTErrConvertFromWin32(GetLastError()); 340 LocalFree(pSecDesc); 275 341 } 276 342 return rc; … … 295 361 *phNmPipe = INVALID_HANDLE_VALUE; 296 362 363 /* 364 * Create a security descriptor blocking access to the pipe via network. 365 */ 297 366 PSECURITY_DESCRIPTOR pSecDesc; 298 367 int rc = rtLocalIpcServerWinAllocSecurityDescriptor(&pSecDesc, fFirst /* Server? */); 299 368 if (RT_SUCCESS(rc)) 300 369 { 370 #if 0 371 { /* Just for checking the security descriptor out in the debugger (!sd <addr> doesn't work): */ 372 DWORD dwRet = LookupSecurityDescriptorPartsW(NULL, NULL, NULL, NULL, NULL, NULL, pSecDesc); 373 __debugbreak(); RT_NOREF(dwRet); 374 375 PTRUSTEE_W pOwner = NULL; 376 PTRUSTEE_W pGroup = NULL; 377 ULONG cAces = 0; 378 PEXPLICIT_ACCESS_W paAces = NULL; 379 ULONG cAuditEntries = 0; 380 PEXPLICIT_ACCESS_W paAuditEntries = NULL; 381 dwRet = LookupSecurityDescriptorPartsW(&pOwner, NULL, NULL, NULL, NULL, NULL, pSecDesc); 382 dwRet = LookupSecurityDescriptorPartsW(NULL, &pGroup, NULL, NULL, NULL, NULL, pSecDesc); 383 dwRet = LookupSecurityDescriptorPartsW(NULL, NULL, &cAces, &paAces, NULL, NULL, pSecDesc); 384 dwRet = LookupSecurityDescriptorPartsW(NULL, NULL, NULL, NULL, &cAuditEntries, &paAuditEntries, pSecDesc); 385 __debugbreak(); RT_NOREF(dwRet); 386 } 387 #endif 388 389 /* 390 * Now, create the pipe. 391 */ 301 392 SECURITY_ATTRIBUTES SecAttrs; 302 393 SecAttrs.nLength = sizeof(SECURITY_ATTRIBUTES); … … 321 412 30*1000, /* nDefaultTimeOut = 30 sec */ 322 413 &SecAttrs); /* lpSecurityAttributes */ 323 LocalFree(pSecDesc);324 414 if (hNmPipe != INVALID_HANDLE_VALUE) 415 { 416 #if 0 /* For checking access control stuff in windbg (doesn't work): */ 417 PSECURITY_DESCRIPTOR pSecDesc2 = NULL; 418 PACL pDacl = NULL; 419 DWORD dwRet; 420 dwRet = GetSecurityInfo(hNmPipe, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSecDesc2); 421 PACL pSacl = NULL; 422 dwRet = GetSecurityInfo(hNmPipe, SE_FILE_OBJECT, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &pSacl, &pSecDesc2); 423 dwRet = GetSecurityInfo(hNmPipe, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, &pSacl, &pSecDesc2); 424 PSID pSidOwner = NULL; 425 dwRet = GetSecurityInfo(hNmPipe, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSecDesc2); 426 PSID pSidGroup = NULL; 427 dwRet = GetSecurityInfo(hNmPipe, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, NULL, &pSidGroup, NULL, NULL, &pSecDesc2); 428 __debugbreak(); 429 RT_NOREF(dwRet); 430 #endif 325 431 *phNmPipe = hNmPipe; 432 rc = VINF_SUCCESS; 433 } 326 434 else 327 435 rc = RTErrConvertFromWin32(GetLastError()); 328 }329 436 LocalFree(pSecDesc); 437 } 330 438 return rc; 331 439 }
Note:
See TracChangeset
for help on using the changeset viewer.