Changeset 29289 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- May 10, 2010 9:38:30 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/win/process-win.cpp
r29004 r29289 70 70 typedef FNCREATEPROCESSWITHLOGON *PFNCREATEPROCESSWITHLOGON; 71 71 72 typedef DWORD WINAPI FNWTSGETACTIVECONSOLESESSIONID(); 73 typedef FNWTSGETACTIVECONSOLESESSIONID *PFNWTSGETACTIVECONSOLESESSIONID; 74 75 typedef BOOL WINAPI FNWTSQUERYUSERTOKEN(ULONG, PHANDLE); 76 typedef FNWTSQUERYUSERTOKEN *PFNWTSQUERYUSERTOKEN; 77 72 78 73 79 /******************************************************************************* … … 237 243 static int rtProcCreateAsUserHlp(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszExec, PRTUTF16 pwszCmdLine, 238 244 PRTUTF16 pwszzBlock, DWORD dwCreationFlags, 239 STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo) 240 { 241 /** @todo On NT4 we need to enable the SeTcbPrivilege to act as part of the operating system. Otherwise 242 * we will get error 1314 (priviledge not held) as a response. */ 243 244 /* 245 * The following rights are needed in order to use LogonUserW and 246 * CreateProcessAsUserW, so the local policy has to be modified to: 247 * - SE_TCB_NAME = Act as part of the operating system 248 * - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object 249 * - SE_INCREASE_QUOTA_NAME 250 * 251 * We may fail here with ERROR_PRIVILEGE_NOT_HELD. 252 */ 253 int rc; 254 DWORD dwErr = NO_ERROR; 245 STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo, uint32_t fFlags) 246 { 255 247 HANDLE hToken = INVALID_HANDLE_VALUE; 256 BOOL fRc = LogonUserW(pwszUser, 257 NULL, /* lpDomain */ 258 pwszPassword, 259 LOGON32_LOGON_INTERACTIVE, 260 LOGON32_PROVIDER_DEFAULT, 261 &hToken); 248 BOOL fRc = FALSE; 249 #ifndef IPRT_TARGET_NT4 250 /* 251 * Get the session ID. 252 */ 253 DWORD dwSessionID = 0; /* On W2K the session ID is always 0 (does not have fast user switching). */ 254 RTLDRMOD hKernel32; 255 int rc = RTLdrLoad("Kernel32.dll", &hKernel32); 256 if (RT_SUCCESS(rc)) 257 { 258 PFNWTSGETACTIVECONSOLESESSIONID pfnWTSGetActiveConsoleSessionId; 259 rc = RTLdrGetSymbol(hKernel32, "WTSGetActiveConsoleSessionId", (void **)&pfnWTSGetActiveConsoleSessionId); 260 if (RT_SUCCESS(rc)) 261 { 262 /* 263 * Console session means the session which the physical keyboard and mouse 264 * is connected to. Due to FUS (fast user switching) starting with Windows XP 265 * this can be a different session than 0. 266 */ 267 dwSessionID = pfnWTSGetActiveConsoleSessionId(); /* Get active console session ID. */ 268 } 269 RTLdrClose(hKernel32); 270 } 271 272 if (fFlags & RTPROC_FLAGS_SERVICE) 273 { 274 /* 275 * Get the current user token. 276 */ 277 RTLDRMOD hWtsAPI32; 278 rc = RTLdrLoad("Wtsapi32.dll", &hWtsAPI32); 279 if (RT_SUCCESS(rc)) 280 { 281 /* Note that WTSQueryUserToken() only is available on Windows XP and up! */ 282 PFNWTSQUERYUSERTOKEN pfnWTSQueryUserToken; 283 rc = RTLdrGetSymbol(hWtsAPI32, "WTSQueryUserToken", (void **)&pfnWTSQueryUserToken); 284 if (RT_SUCCESS(rc)) 285 fRc = pfnWTSQueryUserToken(dwSessionID, &hToken); 286 RTLdrClose(hWtsAPI32); 287 } 288 } 289 #endif /* !IPRT_TARGET_NT4 */ 290 291 DWORD dwErr = NO_ERROR; 292 /* 293 * If not run by a service, use the normal LogonUserW function in order 294 * to run the child process with different credentials using the returned 295 * primary token. 296 */ 297 if (!(fFlags & RTPROC_FLAGS_SERVICE)) 298 { 299 /* 300 * The following rights are needed in order to use LogonUserW and 301 * CreateProcessAsUserW, so the local policy has to be modified to: 302 * - SE_TCB_NAME = Act as part of the operating system 303 * - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object 304 * - SE_INCREASE_QUOTA_NAME 305 * 306 * We may fail here with ERROR_PRIVILEGE_NOT_HELD. 307 */ 308 fRc = LogonUserW(pwszUser, 309 NULL, /* lpDomain */ 310 pwszPassword, 311 LOGON32_LOGON_INTERACTIVE, 312 LOGON32_PROVIDER_DEFAULT, 313 &hToken); 314 } 315 262 316 if (fRc) 263 317 { 264 fRc = CreateProcessAsUserW(hToken, 265 pwszExec, 266 pwszCmdLine, 267 NULL, /* pProcessAttributes */ 268 NULL, /* pThreadAttributes */ 269 TRUE, /* fInheritHandles */ 270 dwCreationFlags, 271 pwszzBlock, 272 NULL, /* pCurrentDirectory */ 273 pStartupInfo, 274 pProcInfo); 275 if (!fRc) 276 dwErr = GetLastError(); 318 #ifndef IPRT_TARGET_NT4 319 HANDLE hDuplicatedToken = INVALID_HANDLE_VALUE; 320 HANDLE hProcessToken = INVALID_HANDLE_VALUE; 321 322 /* 323 * If used by a service, open this service process and adjust 324 * privileges by enabling the SE_TCB_NAME right to act as part 325 * of the operating system. 326 */ 327 if (fFlags & RTPROC_FLAGS_SERVICE) 328 { 329 TOKEN_PRIVILEGES privToken, privTokenOld; 330 DWORD dwTokenSize; 331 332 fRc = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hProcessToken); 333 if ( fRc 334 && LookupPrivilegeValue(NULL, SE_TCB_NAME, &privToken.Privileges[0].Luid)) 335 { 336 privToken.PrivilegeCount = 1; 337 privToken.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 338 fRc = AdjustTokenPrivileges(hProcessToken, FALSE, &privToken, sizeof(privToken), &privTokenOld, &dwTokenSize); 339 if (!fRc) 340 dwErr = GetLastError(); 341 } 342 } 343 344 if ( dwErr == ERROR_SUCCESS 345 || dwErr == ERROR_NOT_ALL_ASSIGNED) /* The AdjustTokenPrivileges() did not succeed, but this isn't fatal. */ 346 { 347 fRc = DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hDuplicatedToken); 348 #if 0 349 /* 350 * Assign the current session ID (> 0 on Windows Vista and up) to the primary token we just duplicated. 351 ** @todo This does not work yet, needs more investigation! */ 352 */ 353 if (fRc) 354 { 355 fRc = SetTokenInformation(hDuplicatedToken, TokenSessionId, &dwSessionID, sizeof(DWORD)); 356 if (!fRc) 357 dwErr = GetLastError(); 358 } 359 else 360 dwErr = GetLastError(); 361 #endif 362 } 363 364 #endif /* !IPRT_TARGET_NT4 */ 365 366 /** @todo On NT4 we need to enable the SeTcbPrivilege to act as part of the operating system. Otherwise 367 * we will get error 1314 (priviledge not held) as a response. */ 368 369 /* Hopefully having a valid token now! */ 370 if ( fRc 371 #ifdef IPRT_TARGET_NT4 372 && hToken != INVALID_HANDLE_VALUE 373 #else 374 && hDuplicatedToken != INVALID_HANDLE_VALUE 375 #endif /* IPRT_TARGET_NT4 */ 376 ) 377 { 378 fRc = CreateProcessAsUserW( 379 #ifdef IPRT_TARGET_NT4 380 hToken, 381 #else 382 hDuplicatedToken, 383 #endif /* !IPRT_TARGET_NT4 */ 384 pwszExec, 385 pwszCmdLine, 386 NULL, /* pProcessAttributes */ 387 NULL, /* pThreadAttributes */ 388 TRUE, /* fInheritHandles */ 389 dwCreationFlags, 390 pwszzBlock, 391 NULL, /* pCurrentDirectory */ 392 pStartupInfo, 393 pProcInfo); 394 if (!fRc) 395 dwErr = GetLastError(); 396 #ifndef IPRT_TARGET_NT4 397 CloseHandle(hDuplicatedToken); 398 #endif /* !IPRT_TARGET_NT4 */ 399 } 277 400 CloseHandle(hToken); 401 #ifndef IPRT_TARGET_NT4 402 if (fFlags & RTPROC_FLAGS_SERVICE) 403 { 404 /** @todo Drop SE_TCB_NAME priviledge before closing the process handle! */ 405 if (hProcessToken != INVALID_HANDLE_VALUE) 406 CloseHandle(hProcessToken); 407 } 408 #endif /* !IPRT_TARGET_NT4 */ 278 409 } 279 410 else … … 317 448 } 318 449 } 319 #endif 450 #endif /* !IPRT_TARGET_NT4 */ 320 451 321 452 if (dwErr != NO_ERROR) … … 335 466 AssertPtrReturn(pszExec, VERR_INVALID_POINTER); 336 467 AssertReturn(*pszExec, VERR_INVALID_PARAMETER); 337 AssertReturn(!(fFlags & ~(RTPROC_FLAGS_DAEMONIZE_DEPRECATED | RTPROC_FLAGS_DETACHED )), VERR_INVALID_PARAMETER);468 AssertReturn(!(fFlags & ~(RTPROC_FLAGS_DAEMONIZE_DEPRECATED | RTPROC_FLAGS_DETACHED | RTPROC_FLAGS_SERVICE)), VERR_INVALID_PARAMETER); 338 469 AssertReturn(!(fFlags & RTPROC_FLAGS_DETACHED) || !phProcess, VERR_INVALID_PARAMETER); 339 470 AssertReturn(hEnv != NIL_RTENV, VERR_INVALID_PARAMETER); … … 487 618 rc = rtProcCreateAsUserHlp(pwszUser, pwszPassword, 488 619 pwszExec, pwszCmdLine, pwszzBlock, dwCreationFlags, 489 &StartupInfo, &ProcInfo );620 &StartupInfo, &ProcInfo, fFlags); 490 621 491 622 RTUtf16Free(pwszPassword);
Note:
See TracChangeset
for help on using the changeset viewer.