604 lines
14 KiB
Plaintext
604 lines
14 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Sudo Test Scenarios\n",
|
|
"\n",
|
|
"Obviously, automated tests that require going through a UAC are challenging to write as unit tests, or run in CI. This notebook instead provides a way of listing a bunch of manual tests. This is all powered by the VsCode Polyglot Notebooks extension. Make sure you have that installed, so that you can run this notebook. \n",
|
|
"\n",
|
|
"(You'll need the [Polyglot Notebooks](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) extension for VsCode installed to run this notebook.)\n",
|
|
"\n",
|
|
"## Building\n",
|
|
"\n",
|
|
"First, start by building the code. We're going to stick the output exe into a `_sudo_` alias, to keep tests concise. \n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"cargo build --target x86_64-pc-windows-msvc\n",
|
|
"new-alias -Force _sudo_ ..\\target\\x86_64-pc-windows-msvc\\debug\\sudo.exe"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"new-alias -Force _sudo_ ..\\target\\x86_64-pc-windows-msvc\\debug\\sudo.exe"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Tests\n",
|
|
"\n",
|
|
"### Simple sanity tests\n",
|
|
"Just start py printing the error message:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Dismiss this UAC. We should print an error message."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ cmd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Running `sudo notepad` should elevate Notepad directly without triggering a UAC prompt for `notepad`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ notepad"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Running `sudo --newWindow cmd` should elevate \"Command Prompt\" directly and spawn a new conhost."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ --newWindow cmd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Running `sudo netstat -ab` should display network statistics and the process using them."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ netstat -ab"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Exiting `netstat` and `sudo` using Ctrl+C should terminate the processes. This test is going to spawn a new CMD in a new conhost window, ctrl+c in that window to verify it did work. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"conhost -- cmd.exe /k ..\\target\\x86_64-pc-windows-msvc\\debug\\sudo.exe netstat -ab"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Redirecting to pipes and files\n",
|
|
"\n",
|
|
"This command uses `dir /b` to list the contents of the directory, and `find /c /v \"\"` to count the lines (items) returned.\n",
|
|
"This should print a number greater than 0 if there are items in the directory."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ cmd /c dir /b \"C:\\Program Files\\WindowsApps\" `| find /c /v \"\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Env vars\n",
|
|
"\n",
|
|
"Running `sudo cmd`, without -E, doesn't propogate the environment variables. You should get `FooBar was %FooBar%`"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"$env:FooBar = \"Hello World\"\n",
|
|
"_sudo_ cmd /c echo FooBar was '%FooBar%'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Running `sudo -E ...` should pass the env vars to the child process."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"$env:FooBar = \"Hello World\"\n",
|
|
"_sudo_ -E cmd /c echo FooBar was '%FooBar%'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Running `sudo -E` with no command should not crash."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ -E"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Running `sudo -N -E cmd` should elevate `sudo` directly, spawn a new conhost, and retain env vars. (The output will appear here in the notebook - close the conhost to continue.)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"$env:FooBar = \"Hello new window\"\n",
|
|
"_sudo_ --new-window -E cmd /k echo FooBar was '%FooBar%'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Running `..\\target\\x86_64-pc-windows-msvc\\debug\\sudo.exe cmd` from an admin prompt should silently launch CMD without triggering UAC. (you'll need to paste this into the conhost that appears manually)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"Start-Process -verb runas cmd -ArgumentList \"/k cd /d $((Get-Location).Path)\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### CMD intrinsics tests\n",
|
|
"\n",
|
|
"Running `sudo dir`, FROM CMD, should list the files in the current working directory. (Recall, we're in the `/tools` dir)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"cmd /c ..\\target\\x86_64-pc-windows-msvc\\debug\\sudo.exe dir"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Of course, the notebook is running PowerShell. So, running `sudo dir` from PowerShell should not list files in the current working directory."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ dir"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Running the command `target\\x86_64-pc-windows-msvc\\debug\\sudo.exe fsutil volume allocationReport C: > out.txt`, then typing `out.txt` should display content in the text file.\n",
|
|
"\n",
|
|
"Ensure that the text file is not empty. This usually takes like 15-20 seconds to run, so patience. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"if (Test-Path -Path \"out.txt\") { Remove-Item -Path \"out.txt\" }\n",
|
|
"_sudo_ fsutil volume allocationReport C: > out.txt\n",
|
|
"(get-childItem -path out.txt).Length -gt 0\n",
|
|
"Remove-Item -Path \"out.txt\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Setting Modes\n",
|
|
"\n",
|
|
"\n",
|
|
"Running `sudo --inline cmd` should exit with an error when `sudo` is set to disable input mode."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ ..\\target\\x86_64-pc-windows-msvc\\debug\\sudo.exe config --enable disableInput\n",
|
|
"_sudo_ --inline cmd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Same as above, but with `sudo --disable-input cmd` should exit with an error when `sudo` is set to force new window mode."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ ..\\target\\x86_64-pc-windows-msvc\\debug\\sudo.exe config --enable forceNewWindow\n",
|
|
"_sudo_ --disable-input cmd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Now, back to normal mode"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ ..\\target\\x86_64-pc-windows-msvc\\debug\\sudo.exe config --enable normal"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Working directories\n",
|
|
"\n",
|
|
"Running `sudo -N cmd` in any path should start `cmd` in `C:\\windows\\system32`. (this will open a conhost in a new window)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ -N cmd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Running `sudo -D . -N cmd` in any path should start in the original path. (the `/tools` directory)\n",
|
|
"\n",
|
|
"(again, output will actually appear in the notebook, close the conhost to continue)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ -D . -N cmd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"This next one is a bit wacky. Search paths are... complicated. \n",
|
|
"\n",
|
|
"We're going to copy our built binary into system32 (under a different name, so it doesn't kill your existing sudo). \n",
|
|
"Then, we're going to copy `cmd` into a different path, one that's relative to our CWD. \n",
|
|
"\n",
|
|
"Then, we're going to run `sudo2 ..\\cmd.exe`. This should run the `cmd` from the relative path, not the one in system32. We can verify this by looking at the conhost that's spawned. It should display an error at the start like:\n",
|
|
"\n",
|
|
"```\n",
|
|
"The system cannot find message text for message number 0x2350 in the message file for Application.\n",
|
|
"\n",
|
|
"(c) Microsoft Corporation. All rights reserved.\n",
|
|
"Not enough memory resources are available to process this command.\n",
|
|
"```\n",
|
|
"\n",
|
|
"There will be two UACs to accept. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"dotnet_interactive": {
|
|
"language": "pwsh"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelName": "pwsh"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"_sudo_ cmd /c copy ..\\target\\x86_64-pc-windows-msvc\\debug\\sudo.exe C:\\Windows\\System32\\sudo2.exe /y\n",
|
|
"copy-item c:\\windows\\system32\\cmd.exe -destination .. -force\n",
|
|
"c:\\windows\\system32\\sudo2.exe -N ..\\cmd.exe\n",
|
|
"rm ..\\cmd.exe"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": ".NET (PowerShell)",
|
|
"language": "PowerShell",
|
|
"name": ".net-pwsh"
|
|
},
|
|
"language_info": {
|
|
"name": "polyglot-notebook"
|
|
},
|
|
"polyglot_notebook": {
|
|
"kernelInfo": {
|
|
"defaultKernelName": "pwsh",
|
|
"items": [
|
|
{
|
|
"aliases": [],
|
|
"languageName": "pwsh",
|
|
"name": "pwsh"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|