diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2022-03-30 17:05:56 -0500 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2022-04-01 22:06:11 -0500 |
| commit | ae3a31795614000207470e6824887c414366a681 (patch) | |
| tree | 7c3c659ee5efdbc7b4c7c93108221b229c26fd2d /src/burn/engine/exeengine.cpp | |
| parent | e7a208587389a17fa5ff3654d533e023268bfddf (diff) | |
| download | wix-ae3a31795614000207470e6824887c414366a681.tar.gz wix-ae3a31795614000207470e6824887c414366a681.tar.bz2 wix-ae3a31795614000207470e6824887c414366a681.zip | |
Minimize chance of user arguments messing up the command line
to avoid variations of issue 3890
Diffstat (limited to 'src/burn/engine/exeengine.cpp')
| -rw-r--r-- | src/burn/engine/exeengine.cpp | 83 |
1 files changed, 45 insertions, 38 deletions
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp index 9754002f..0a2084e5 100644 --- a/src/burn/engine/exeengine.cpp +++ b/src/burn/engine/exeengine.cpp | |||
| @@ -362,12 +362,12 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
| 362 | { | 362 | { |
| 363 | HRESULT hr = S_OK; | 363 | HRESULT hr = S_OK; |
| 364 | LPCWSTR wzArguments = NULL; | 364 | LPCWSTR wzArguments = NULL; |
| 365 | LPWSTR sczArguments = NULL; | ||
| 366 | LPWSTR sczArgumentsFormatted = NULL; | ||
| 367 | LPWSTR sczArgumentsObfuscated = NULL; | ||
| 368 | LPWSTR sczCachedDirectory = NULL; | 365 | LPWSTR sczCachedDirectory = NULL; |
| 369 | LPWSTR sczExecutablePath = NULL; | 366 | LPWSTR sczExecutablePath = NULL; |
| 370 | LPWSTR sczCommand = NULL; | 367 | LPWSTR sczBaseCommand = NULL; |
| 368 | LPWSTR sczUnformattedUserArgs = NULL; | ||
| 369 | LPWSTR sczUserArgs = NULL; | ||
| 370 | LPWSTR sczUserArgsObfuscated = NULL; | ||
| 371 | LPWSTR sczCommandObfuscated = NULL; | 371 | LPWSTR sczCommandObfuscated = NULL; |
| 372 | HANDLE hExecutableFile = INVALID_HANDLE_VALUE; | 372 | HANDLE hExecutableFile = INVALID_HANDLE_VALUE; |
| 373 | DWORD dwExitCode = 0; | 373 | DWORD dwExitCode = 0; |
| @@ -406,7 +406,7 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | // now add optional arguments | 408 | // now add optional arguments |
| 409 | hr = StrAllocString(&sczArguments, wzArguments && *wzArguments ? wzArguments : L"", 0); | 409 | hr = StrAllocString(&sczUnformattedUserArgs, wzArguments && *wzArguments ? wzArguments : L"", 0); |
| 410 | ExitOnFailure(hr, "Failed to copy package arguments."); | 410 | ExitOnFailure(hr, "Failed to copy package arguments."); |
| 411 | 411 | ||
| 412 | for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i) | 412 | for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i) |
| @@ -419,23 +419,23 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
| 419 | 419 | ||
| 420 | if (fCondition) | 420 | if (fCondition) |
| 421 | { | 421 | { |
| 422 | hr = StrAllocConcat(&sczArguments, L" ", 0); | 422 | hr = StrAllocConcat(&sczUnformattedUserArgs, L" ", 0); |
| 423 | ExitOnFailure(hr, "Failed to separate command-line arguments."); | 423 | ExitOnFailure(hr, "Failed to separate command-line arguments."); |
| 424 | 424 | ||
| 425 | switch (pExecuteAction->exePackage.action) | 425 | switch (pExecuteAction->exePackage.action) |
| 426 | { | 426 | { |
| 427 | case BOOTSTRAPPER_ACTION_STATE_INSTALL: | 427 | case BOOTSTRAPPER_ACTION_STATE_INSTALL: |
| 428 | hr = StrAllocConcat(&sczArguments, commandLineArgument->sczInstallArgument, 0); | 428 | hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczInstallArgument, 0); |
| 429 | ExitOnFailure(hr, "Failed to get command-line argument for install."); | 429 | ExitOnFailure(hr, "Failed to get command-line argument for install."); |
| 430 | break; | 430 | break; |
| 431 | 431 | ||
| 432 | case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: | 432 | case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: |
| 433 | hr = StrAllocConcat(&sczArguments, commandLineArgument->sczUninstallArgument, 0); | 433 | hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczUninstallArgument, 0); |
| 434 | ExitOnFailure(hr, "Failed to get command-line argument for uninstall."); | 434 | ExitOnFailure(hr, "Failed to get command-line argument for uninstall."); |
| 435 | break; | 435 | break; |
| 436 | 436 | ||
| 437 | case BOOTSTRAPPER_ACTION_STATE_REPAIR: | 437 | case BOOTSTRAPPER_ACTION_STATE_REPAIR: |
| 438 | hr = StrAllocConcat(&sczArguments, commandLineArgument->sczRepairArgument, 0); | 438 | hr = StrAllocConcat(&sczUnformattedUserArgs, commandLineArgument->sczRepairArgument, 0); |
| 439 | ExitOnFailure(hr, "Failed to get command-line argument for repair."); | 439 | ExitOnFailure(hr, "Failed to get command-line argument for repair."); |
| 440 | break; | 440 | break; |
| 441 | 441 | ||
| @@ -446,71 +446,68 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
| 446 | } | 446 | } |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | // build command | 449 | // build base command |
| 450 | AppAppendCommandLineArgument(&sczCommand, sczExecutablePath); | 450 | hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath); |
| 451 | ExitOnFailure(hr, "Failed to create executable command."); | 451 | ExitOnFailure(hr, "Failed to allocate base command."); |
| 452 | 452 | ||
| 453 | if (pPackage->Exe.fBundle) | 453 | if (pPackage->Exe.fBundle) |
| 454 | { | 454 | { |
| 455 | hr = StrAllocConcat(&sczCommand, L" -norestart", 0); | 455 | hr = StrAllocConcat(&sczBaseCommand, L" -norestart", 0); |
| 456 | ExitOnFailure(hr, "Failed to append quiet argument."); | 456 | ExitOnFailure(hr, "Failed to append norestart argument."); |
| 457 | 457 | ||
| 458 | // Add the list of dependencies to ignore, if any, to the burn command line. | 458 | // Add the list of dependencies to ignore, if any, to the burn command line. |
| 459 | if (pExecuteAction->exePackage.sczIgnoreDependencies) | 459 | if (pExecuteAction->exePackage.sczIgnoreDependencies) |
| 460 | { | 460 | { |
| 461 | hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies); | 461 | hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies); |
| 462 | ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); | 462 | ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); |
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | // Add the list of ancestors, if any, to the burn command line. | 465 | // Add the list of ancestors, if any, to the burn command line. |
| 466 | if (pExecuteAction->exePackage.sczAncestors) | 466 | if (pExecuteAction->exePackage.sczAncestors) |
| 467 | { | 467 | { |
| 468 | hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors); | 468 | hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors); |
| 469 | ExitOnFailure(hr, "Failed to append the list of ancestors to the command line."); | 469 | ExitOnFailure(hr, "Failed to append the list of ancestors to the command line."); |
| 470 | } | 470 | } |
| 471 | 471 | ||
| 472 | if (pExecuteAction->exePackage.sczEngineWorkingDirectory) | 472 | if (pExecuteAction->exePackage.sczEngineWorkingDirectory) |
| 473 | { | 473 | { |
| 474 | hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczCommand, NULL); | 474 | hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczBaseCommand, NULL); |
| 475 | ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line."); | 475 | ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line."); |
| 476 | } | 476 | } |
| 477 | 477 | ||
| 478 | hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL); | 478 | hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczBaseCommand, NULL); |
| 479 | ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); | 479 | ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); |
| 480 | } | 480 | } |
| 481 | 481 | ||
| 482 | // Always add user supplied arguments last. | 482 | // build user args |
| 483 | if (sczArguments && *sczArguments) | 483 | if (sczUnformattedUserArgs && *sczUnformattedUserArgs) |
| 484 | { | 484 | { |
| 485 | hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL); | 485 | hr = VariableFormatString(pVariables, sczUnformattedUserArgs, &sczUserArgs, NULL); |
| 486 | ExitOnFailure(hr, "Failed to format argument string."); | 486 | ExitOnFailure(hr, "Failed to format argument string."); |
| 487 | 487 | ||
| 488 | hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL); | 488 | hr = VariableFormatStringObfuscated(pVariables, sczUnformattedUserArgs, &sczUserArgsObfuscated, NULL); |
| 489 | ExitOnFailure(hr, "Failed to format obfuscated argument string."); | 489 | ExitOnFailure(hr, "Failed to format obfuscated argument string."); |
| 490 | 490 | ||
| 491 | hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated); | 491 | hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczBaseCommand, sczUserArgsObfuscated); |
| 492 | ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments."); | 492 | ExitOnFailure(hr, "Failed to allocate obfuscated exe command."); |
| 493 | |||
| 494 | hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted); | ||
| 495 | ExitOnFailure(hr, "Failed to copy formatted arguments."); | ||
| 496 | } | 493 | } |
| 497 | 494 | ||
| 498 | // Log before we add the secret pipe name and client token for embedded processes. | 495 | // Log obfuscated command, which won't include raw hidden variable values or protocol specific arguments to avoid exposing secrets. |
| 499 | LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated); | 496 | LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated ? sczCommandObfuscated : sczBaseCommand); |
| 500 | 497 | ||
| 501 | if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) | 498 | if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) |
| 502 | { | 499 | { |
| 503 | hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); | 500 | hr = EmbeddedRunBundle(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode); |
| 504 | ExitOnFailure(hr, "Failed to run exe with Burn protocol from path: %ls", sczExecutablePath); | 501 | ExitOnFailure(hr, "Failed to run exe with Burn protocol from path: %ls", sczExecutablePath); |
| 505 | } | 502 | } |
| 506 | else if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol) | 503 | else if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol) |
| 507 | { | 504 | { |
| 508 | hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); | 505 | hr = NetFxRunChainer(sczExecutablePath, sczBaseCommand, sczUserArgs, pfnGenericMessageHandler, pvContext, &dwExitCode); |
| 509 | ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath); | 506 | ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath); |
| 510 | } | 507 | } |
| 511 | else | 508 | else |
| 512 | { | 509 | { |
| 513 | hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczCommand, sczCachedDirectory, &dwExitCode); | 510 | hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczBaseCommand, sczUserArgs, sczCachedDirectory, &dwExitCode); |
| 514 | ExitOnFailure(hr, "Failed to run EXE process"); | 511 | ExitOnFailure(hr, "Failed to run EXE process"); |
| 515 | } | 512 | } |
| 516 | 513 | ||
| @@ -518,12 +515,12 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
| 518 | ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); | 515 | ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); |
| 519 | 516 | ||
| 520 | LExit: | 517 | LExit: |
| 521 | StrSecureZeroFreeString(sczArguments); | ||
| 522 | StrSecureZeroFreeString(sczArgumentsFormatted); | ||
| 523 | ReleaseStr(sczArgumentsObfuscated); | ||
| 524 | ReleaseStr(sczCachedDirectory); | 518 | ReleaseStr(sczCachedDirectory); |
| 525 | ReleaseStr(sczExecutablePath); | 519 | ReleaseStr(sczExecutablePath); |
| 526 | StrSecureZeroFreeString(sczCommand); | 520 | ReleaseStr(sczBaseCommand); |
| 521 | ReleaseStr(sczUnformattedUserArgs); | ||
| 522 | StrSecureZeroFreeString(sczUserArgs); | ||
| 523 | ReleaseStr(sczUserArgsObfuscated); | ||
| 527 | ReleaseStr(sczCommandObfuscated); | 524 | ReleaseStr(sczCommandObfuscated); |
| 528 | 525 | ||
| 529 | ReleaseFileHandle(hExecutableFile); | 526 | ReleaseFileHandle(hExecutableFile); |
| @@ -540,12 +537,14 @@ extern "C" HRESULT ExeEngineRunProcess( | |||
| 540 | __in LPVOID pvContext, | 537 | __in LPVOID pvContext, |
| 541 | __in BURN_PACKAGE* pPackage, | 538 | __in BURN_PACKAGE* pPackage, |
| 542 | __in_z LPCWSTR wzExecutablePath, | 539 | __in_z LPCWSTR wzExecutablePath, |
| 543 | __in_z LPWSTR wzCommand, | 540 | __in_z LPWSTR sczBaseCommand, |
| 541 | __in_z_opt LPCWSTR wzUserArgs, | ||
| 544 | __in_z_opt LPCWSTR wzCachedDirectory, | 542 | __in_z_opt LPCWSTR wzCachedDirectory, |
| 545 | __inout DWORD* pdwExitCode | 543 | __inout DWORD* pdwExitCode |
| 546 | ) | 544 | ) |
| 547 | { | 545 | { |
| 548 | HRESULT hr = S_OK; | 546 | HRESULT hr = S_OK; |
| 547 | LPWSTR sczCommand = NULL; | ||
| 549 | STARTUPINFOW si = { }; | 548 | STARTUPINFOW si = { }; |
| 550 | PROCESS_INFORMATION pi = { }; | 549 | PROCESS_INFORMATION pi = { }; |
| 551 | GENERIC_EXECUTE_MESSAGE message = { }; | 550 | GENERIC_EXECUTE_MESSAGE message = { }; |
| @@ -555,10 +554,17 @@ extern "C" HRESULT ExeEngineRunProcess( | |||
| 555 | BOOL fFireAndForget = BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fFireAndForget; | 554 | BOOL fFireAndForget = BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fFireAndForget; |
| 556 | BOOL fInheritHandles = BURN_PACKAGE_TYPE_BUNDLE == pPackage->type; | 555 | BOOL fInheritHandles = BURN_PACKAGE_TYPE_BUNDLE == pPackage->type; |
| 557 | 556 | ||
| 557 | // Always add user supplied arguments last. | ||
| 558 | if (wzUserArgs) | ||
| 559 | { | ||
| 560 | hr = StrAllocFormattedSecure(&sczCommand, L"%ls %ls", sczBaseCommand, wzUserArgs); | ||
| 561 | ExitOnFailure(hr, "Failed to append user args."); | ||
| 562 | } | ||
| 563 | |||
| 558 | // Make the cache location of the executable the current directory to help those executables | 564 | // Make the cache location of the executable the current directory to help those executables |
| 559 | // that expect stuff to be relative to them. | 565 | // that expect stuff to be relative to them. |
| 560 | si.cb = sizeof(si); | 566 | si.cb = sizeof(si); |
| 561 | if (!::CreateProcessW(wzExecutablePath, wzCommand, NULL, NULL, fInheritHandles, CREATE_NO_WINDOW, NULL, wzCachedDirectory, &si, &pi)) | 567 | if (!::CreateProcessW(wzExecutablePath, sczCommand ? sczCommand : sczBaseCommand, NULL, NULL, fInheritHandles, CREATE_NO_WINDOW, NULL, wzCachedDirectory, &si, &pi)) |
| 562 | { | 568 | { |
| 563 | ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath); | 569 | ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath); |
| 564 | } | 570 | } |
| @@ -632,6 +638,7 @@ extern "C" HRESULT ExeEngineRunProcess( | |||
| 632 | } | 638 | } |
| 633 | 639 | ||
| 634 | LExit: | 640 | LExit: |
| 641 | StrSecureZeroFreeString(sczCommand); | ||
| 635 | ReleaseHandle(pi.hThread); | 642 | ReleaseHandle(pi.hThread); |
| 636 | ReleaseHandle(pi.hProcess); | 643 | ReleaseHandle(pi.hProcess); |
| 637 | 644 | ||
