Keep the shell configuration and the key out of the user's reach
The user could empty the authorized_keys and break the login of the website, change the shell configuration to break the prompt, and write startup files that zsh reads on every login. The shell configuration and the key are now read-only for the user, and the shell reads its configuration from ~/.zsh, so the files in the home directory are ignored. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e4050cbf05
commit
49c61b6b91
1 changed files with 28 additions and 10 deletions
|
|
@ -59,10 +59,13 @@ function Restore-Keys($target, $source) {
|
|||
[IO.File]::WriteAllText($target, (($keys + $required) -join "`n") + "`n")
|
||||
}
|
||||
|
||||
# The permissions of the home directory and of the files in it that have to stay: the user may read and write them
|
||||
# and delete their own files, but not the home directory itself and not the files the website needs. Only SYSTEM
|
||||
# and the administrators own them, so the user cannot take the permissions away again.
|
||||
function Set-ProtectedAcl($path, $forDirectory) {
|
||||
# The shell configuration and the key the website logs in with must not change, the four texts may be edited.
|
||||
$readOnly = '.zshrc', '.zshenv', 'authorized_keys'
|
||||
|
||||
# The permissions of the home directory and of the files in it that have to stay: the user may read them and write
|
||||
# the ones that may change, and delete their own files, but not the home directory itself and not the files the
|
||||
# website needs. Only SYSTEM and the administrators own them, so the user cannot take the permissions away again.
|
||||
function Set-ProtectedAcl($path, $forDirectory, $writable) {
|
||||
if (-not $sid) { return }
|
||||
try {
|
||||
$system = New-Object System.Security.Principal.SecurityIdentifier('S-1-5-18')
|
||||
|
|
@ -78,10 +81,12 @@ function Set-ProtectedAcl($path, $forDirectory) {
|
|||
$inheritOnly = [System.Security.AccessControl.PropagationFlags]::InheritOnly
|
||||
$full = [System.Security.AccessControl.FileSystemRights]::FullControl
|
||||
$some = [System.Security.AccessControl.FileSystemRights]::ReadAndExecute -bor [System.Security.AccessControl.FileSystemRights]::Write
|
||||
$read = [System.Security.AccessControl.FileSystemRights]::ReadAndExecute
|
||||
$inherit = if ($forDirectory) { $children } else { $none }
|
||||
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $system, $full, $inherit, $noPropagate, 'Allow'))
|
||||
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $admins, $full, $inherit, $noPropagate, 'Allow'))
|
||||
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $user, $some, $none, $noPropagate, 'Allow'))
|
||||
$userRights = if ($writable) { $some } else { $read }
|
||||
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $user, $userRights, $none, $noPropagate, 'Allow'))
|
||||
if ($forDirectory) {
|
||||
# the files in it are the user's own, they may delete them
|
||||
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $user, $full, $children, $inheritOnly, 'Allow'))
|
||||
|
|
@ -96,7 +101,7 @@ function Set-ProtectedAcl($path, $forDirectory) {
|
|||
# gets MSYS2's default files from /etc/skel, which MSYS2 itself only copies into a home that does not exist yet.
|
||||
function New-Home($path) {
|
||||
New-Item -ItemType Directory -Path $path | Out-Null
|
||||
Set-ProtectedAcl $path $true
|
||||
Set-ProtectedAcl $path $true $true
|
||||
Get-ChildItem -LiteralPath 'C:\msys2\etc\skel' -Force | Copy-Item -Destination $path -Recurse -Force
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +113,7 @@ if (-not (Test-Path -LiteralPath $HomeDir)) {
|
|||
New-Home $HomeDir
|
||||
Write-Log "replaced the link $HomeDir"
|
||||
} else {
|
||||
Set-ProtectedAcl $HomeDir $true
|
||||
Set-ProtectedAcl $HomeDir $true $true
|
||||
}
|
||||
|
||||
foreach ($copy in Get-ChildItem -LiteralPath $copies -Recurse -File -Force) {
|
||||
|
|
@ -119,7 +124,7 @@ foreach ($copy in Get-ChildItem -LiteralPath $copies -Recurse -File -Force) {
|
|||
Remove-Anything $dir
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $dir)) { New-Item -ItemType Directory -Path $dir | Out-Null }
|
||||
Set-ProtectedAcl $dir $true
|
||||
Set-ProtectedAcl $dir $true $true
|
||||
if (Test-Path -LiteralPath $target) {
|
||||
$item = Get-Item -LiteralPath $target -Force
|
||||
if ($item.PSIsContainer -or $item.Attributes -band [IO.FileAttributes]::ReparsePoint) {
|
||||
|
|
@ -135,7 +140,7 @@ foreach ($copy in Get-ChildItem -LiteralPath $copies -Recurse -File -Force) {
|
|||
} else {
|
||||
Copy-Item -LiteralPath $copy.FullName -Destination $target -Force
|
||||
}
|
||||
Set-ProtectedAcl $target $false
|
||||
Set-ProtectedAcl $target $false ($readOnly -notcontains $copy.Name)
|
||||
Write-Log "restored $($copy.Name)"
|
||||
} catch {
|
||||
Write-Log "failed $($copy.Name) : $_"
|
||||
|
|
@ -192,6 +197,11 @@ if (-not ($keys | Where-Object { ($_ -split '\s+')[1] -eq ($required[0] -split '
|
|||
}
|
||||
[IO.File]::WriteAllText((Join-Path $installDir 'restore.ps1'), $restoreScript)
|
||||
|
||||
# The shell configuration used to be in the home directory, the shell reads it from ~/.zsh now.
|
||||
if (Test-Path -LiteralPath (Join-Path $HomeDir '.zsh\.zshrc')) {
|
||||
Remove-Item -LiteralPath (Join-Path $HomeDir '.zshrc') -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$installDir\restore.ps1`" -HomeDir `"$HomeDir`""
|
||||
$triggers = @(
|
||||
New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 30) -RepetitionDuration (New-TimeSpan -Days 3650)
|
||||
|
|
|
|||
Loading…
Reference in a new issue