32 lines
2.6 KiB
JavaScript
32 lines
2.6 KiB
JavaScript
import {spawnSync} from 'node:child_process';
|
|||
|
|
|
||
|
|
// Do not reapply ownership to an already private directory: Windows may require
|
||
|
|
// restore privileges for SetOwner even when the current account already owns it.
|
||
|
|
const command=`$ErrorActionPreference='Stop';
|
||
|
|
$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User;
|
||
|
|
function Test-PrivateAcl($acl){
|
||
|
|
if(-not $acl.AreAccessRulesProtected -or $acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value -ne $sid.Value){return $false;}
|
||
|
|
$rules=@($acl.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier]));
|
||
|
|
if($rules.Count -ne 1){return $false;}
|
||
|
|
$rule=$rules[0];
|
||
|
|
return (-not $rule.IsInherited -and $rule.IdentityReference.Value -eq $sid.Value -and $rule.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and $rule.FileSystemRights -eq [System.Security.AccessControl.FileSystemRights]::FullControl -and $rule.InheritanceFlags -eq ([System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit) -and $rule.PropagationFlags -eq [System.Security.AccessControl.PropagationFlags]::None);
|
||
|
|
}
|
||
|
|
$existing=Get-Acl -LiteralPath $env:SAFETYNET_COLLECTOR_DIRECTORY;
|
||
|
|
$changed=$false;
|
||
|
|
if(-not (Test-PrivateAcl $existing)){
|
||
|
|
$private=New-Object System.Security.AccessControl.DirectorySecurity;
|
||
|
|
$private.SetOwner($sid);$private.SetAccessRuleProtection($true,$false);
|
||
|
|
$private.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule($sid,'FullControl','ContainerInherit,ObjectInherit','None','Allow')));
|
||
|
|
Set-Acl -LiteralPath $env:SAFETYNET_COLLECTOR_DIRECTORY -AclObject $private;
|
||
|
|
$changed=$true;
|
||
|
|
}
|
||
|
|
$verified=Get-Acl -LiteralPath $env:SAFETYNET_COLLECTOR_DIRECTORY;
|
||
|
|
if(-not (Test-PrivateAcl $verified)){throw 'Collector directory protection verification failed';}
|
||
|
|
@{verified=$true;changed=$changed}|ConvertTo-Json -Compress;`;
|
||
|
|
export function protectCollectorDirectory(directory,{run=spawnSync}={}){
|
||
|
|
const result=run('powershell.exe',['-NoProfile','-NonInteractive','-Command',command],{windowsHide:true,timeout:10000,env:{SystemRoot:process.env.SystemRoot,SAFETYNET_COLLECTOR_DIRECTORY:directory},stdio:'pipe',encoding:'utf8'});
|
||
|
|
if(result.status!==0)throw Error('Collector directory protection failed');
|
||
|
|
let proof;try{proof=JSON.parse(result.stdout);}catch{throw Error('Collector directory protection verification failed');}
|
||
|
|
if(proof?.verified!==true||typeof proof.changed!=='boolean')throw Error('Collector directory protection verification failed');
|
||
|
|
return Object.freeze({verified:true,changed:proof.changed});
|
||
|
|
}
|