summaryrefslogtreecommitdiff
path: root/src/burn/engine/exeengine.cpp
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-03-30 17:05:56 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-04-01 22:06:11 -0500
commitae3a31795614000207470e6824887c414366a681 (patch)
tree7c3c659ee5efdbc7b4c7c93108221b229c26fd2d /src/burn/engine/exeengine.cpp
parente7a208587389a17fa5ff3654d533e023268bfddf (diff)
downloadwix-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.cpp83
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
520LExit: 517LExit:
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
634LExit: 640LExit:
641 StrSecureZeroFreeString(sczCommand);
635 ReleaseHandle(pi.hThread); 642 ReleaseHandle(pi.hThread);
636 ReleaseHandle(pi.hProcess); 643 ReleaseHandle(pi.hProcess);
637 644