-
Notifications
You must be signed in to change notification settings - Fork 131
/
sudo.ps1
87 lines (76 loc) · 2.89 KB
/
sudo.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# open question - Should -NoProfile be used when invoking PowerShell
BEGIN {
if ($__SUDO_TEST -ne $true) {
$SUDOEXE = "sudo.exe"
}
else {
if ($null -eq $SUDOEXE) {
throw "variable SUDOEXE has not been set for testing"
}
}
if ([Environment]::OSVersion.Platform -ne "Win32NT") {
throw "This script works only on Microsoft Windows"
}
if ($null -eq (Get-Command -Type Application -Name "$SUDOEXE" -ErrorAction Ignore)) {
throw "'$SUDOEXE' cannot be found."
}
$psProcess = Get-Process -id $PID
if (($null -eq $psProcess) -or ($psProcess.Count -ne 1)) {
throw "Cannot retrieve process for '$PID'"
}
$thisPowerShell = $psProcess.MainModule.FileName
if ($null -eq $thisPowerShell) {
throw "Cannot determine path to '$psProcess'"
}
function convertToBase64EncodedString([string]$cmdLine) {
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmdLine)
[Convert]::ToBase64String($bytes)
}
$MI = $MyInvocation
}
END {
$cmdArguments = $args
# short-circuit if the user provided a scriptblock, then we will use it and ignore any other arguments
if ($cmdArguments.Count -eq 1 -and $cmdArguments[0] -is [scriptblock]) {
$scriptBlock = $cmdArguments[0]
$encodedCommand = convertToBase64EncodedString -cmdLine ($scriptBlock.ToString())
if (($psversiontable.psversion.major -eq 7) -and ($__SUDO_DEBUG -eq $true)) {
Trace-Command -PSHOST -name param* -Expression { & $SUDOEXE "$thisPowerShell" -e $encodedCommand }
}
else {
& $SUDOEXE "$thisPowerShell" -e $encodedCommand
}
return
}
$cmdLine = $MI.Line
$sudoOffset = $cmdLine.IndexOf($MI.InvocationName)
$cmdLineWithoutScript = $cmdLine.SubString($sudoOffset + 5)
$cmdLineAst = [System.Management.Automation.Language.Parser]::ParseInput($cmdLineWithoutScript, [ref]$null, [ref]$null)
$commandAst = $cmdLineAst.Find({$args[0] -is [System.Management.Automation.Language.CommandAst]}, $false)
$commandName = $commandAst.GetCommandName()
$isApplication = Get-Command -Type Application -Name $commandName -ErrorAction Ignore | Select-Object -First 1
$isCmdletOrScript = Get-Command -Type Cmdlet,ExternalScript -Name $commandName -ErrorAction Ignore | Select-Object -First 1
# if the command is a native command, just invoke it
if ($null -ne $isApplication) {
if (($psversiontable.psversion.major -eq 7) -and ($__SUDO_DEBUG -eq $true)) {
trace-command -PSHOST -name param* -Expression { & $SUDOEXE $cmdArguments }
}
else {
& $SUDOEXE $cmdArguments
}
}
elseif ($null -ne $isCmdletOrScript) {
$encodedCommand = convertToBase64EncodedString($cmdLineWithoutScript)
if (($psversiontable.psversion.major -eq 7) -and ($__SUDO_DEBUG -eq $true)) {
trace-command -PSHOST -name param* -Expression { & $SUDOEXE -nologo -e $encodedCommand }
}
else {
& $SUDOEXE $thisPowerShell -nologo -e $encodedCommand
}
}
else {
throw "Cannot find '$commandName'"
}
}