param([string]$cmd) # If there's an error in a call such as $cfg.settings.Lock(), it is important to stop the script. # Continuing at the same time as another application could also be modifying settings can corrupt the settings $ErrorActionPreference = "Stop" $WarningPreference = "Continue" if ($cmd -ne "run") { Write-Host "" Write-Host "This script checks Bitvise SSH Server 9.16+ installations on this computer" Write-Host "for insecure virtual filesystem mount points of type Custom:FlowSfsWin." Write-Host "Such mount points can result after upgrading settings originally created" Write-Host "by SSH Server versions 6.xx and older, after updating first to 7.xx / 8.xx," Write-Host "and later updating directly to SSH Server versions 9.16 - 9.24." Write-Host "" Write-Host "The issue affects SSH Server 7.xx / 8.xx mount points which were configured" Write-Host "with provider type set to Custom, and the provider DLL set to 'FlowSfsWin'," Write-Host "instead of directly using the provider type FlowSfsWin. In these cases," Write-Host "the 'Real root path' associated with the mount point was not preserved" Write-Host "when updating from 7.xx / 8.xx to SSH Server versions 9.16 - 9.24. Instead," Write-Host "these mount points granted unlimited filesystem access after upgrading." Write-Host "" Write-Host "SSH Server versions 9.25+ correct this issue when updating from 7.xx / 8.xx." Write-Host "If settings from 7.xx / 8.xx were already upgraded by 9.16 - 9.24, updating" Write-Host "to 9.25+ cannot fix the affected mount points. Instead, mount points of type" Write-Host "Custom:FlowSfsWin with an empty root path will no longer work. In this case," Write-Host "affected mount points must be fixed by the administrator. You can use this" Write-Host "script to find such mount points in SSH Server settings." Write-Host "" Write-Host "This script finds mount points of type Custom:FlowSfsWin. If any are found:" Write-Host "" Write-Host "- If the 'Custom root path' is empty, a warning is displayed. The mount point" Write-Host " is not changed. The administrator MUST REVIEW and fix such mount points." Write-Host "" Write-Host "- If the 'Custom root path' is configured, the mount type is set to 'Specific" Write-Host " directory' and the 'Real root path' is set to 'Custom root path'. For these" Write-Host " mount points, the changes are saved and no further action is needed." Write-Host "" Write-Host "If you are ready to run this script, invoke it using the parameter 'run':" Write-Host "" Write-Host "powershell run" Write-Host "" Write-Host "The PowerShell instance executing this script must be run with elevated," Write-Host "administrative permissions." Write-Host "" Pause Exit 2 } $cfg = new-object -com "Bitvise.BssCfg" function CheckMountPoints { param($accountOrGroup, [string]$accountOrGroupDesc) $nrCustomToDirectory = 0 $toReview = @() foreach ($mountPoint in $accountOrGroup.xfer.mountPoints.entries) { # Does mountType equal $cfg.enums.SfsMountType.custom? if ($mountPoint.mountType -eq 5) { # Does customProviderDll contain "FlowSfsWin"? if ($mountPoint.customProviderDll -like "FlowSfsWin*") { # Found a Custom:FlowSfsWin mount point # Is customRootPath empty? if ($mountPoint.customRootPath) { # customRootPath is defined. Change to a regular Directory mount point ++$nrCustomToDirectory $mountPoint.mountType = 1 # $cfg.enums.SfsMountType.directory $mountPoint.realRootPath = $mountPoint.customRootPath Write-Host "${accountOrGroupDesc}: Mount point '$($mountPoint.sfsMountPath)' changed from Custom:FlowSfsWin => Directory" } else { # customRootPath is empty. The mount point requires administrator attention $toReview += $mountPoint.sfsMountPath } } } } if ($toReview) { foreach ($mountPath in $toReview) { Write-Warning "${accountOrGroupDesc}: Mount point '$mountPath' must be reviewed" } Write-Host " If unlimited access is intended, change 'Mount type' to 'Unlimited access'" Write-Host " If not, set 'Mount type' to 'Specific directory' and set a 'Real root path'" } return $nrCustomToDirectory } foreach ($instance in $cfg.instances.entries) { Write-Host "" if (-not $instance.canManage) { Write-Host "SSH Server instance '$($instance.name)' cannot be managed using the available COM object" } elseif ($instance.version -lt "9.16") { Write-Host "SSH Server instance '$($instance.name)' cannot be processed by this script until it is updated to a newer version" } else { Write-Host "SSH Server instance '$($instance.name)'" $cfg.SetInstance($instance.name) # Settings must be locked while undergoing change to preserve their integrity. # If you lock settings and do not unlock them, no other process will be able to edit settings until the $cfg object is released. $cfg.settings.Lock() try { $cfg.settings.Load() # Find SSH Server group and account settings entries containing mount points of type Custom with provider set to FlowSfsWin $nrChangesTotal = 0 # Windows groups $nrProcessed = 0 $nrChanged = 0 foreach ($group in $cfg.settings.access.winGroups.entries) { $desc = switch ($group.groupType) { 0 { "Windows group Everyone" } # $cfg.enums.groupType.everyone 1 { "Windows local group '$($group.group)'" } # $cfg.enums.groupType.local 2 { "Windows domain group '$($group.winDomain)\$($group.group)'" } # $cfg.enums.groupType.domain default { "Windows group '$($group.group)'" } } $nrChanges = CheckMountPoints $group $desc $nrChangesTotal += $nrChanges ++$nrProcessed if ($nrChanges) { ++$nrChanged } } Write-Host "Windows groups: $nrProcessed groups checked, $nrChanged changed" # Windows accounts $nrProcessed = 0 $nrChanged = 0 foreach ($account in $cfg.settings.access.winAccounts.entries) { $desc = switch ($account.winAccountType) { 1 { "Windows local account '$($account.winAccount)'" } # $cfg.enums.winAccountType.localAccount 2 { "Windows domain account '$($account.winDomain)\$($account.winAccount)'" } # $cfg.enums.winAccountType.domainAccount 3 { "Microsoft account '$($account.winAccount)'" } # $cfg.enums.winAccountType.microsoftAccount default { "Windows account '$($account.winAccount)'" } } $nrChanges = CheckMountPoints $account $desc $nrChangesTotal += $nrChanges ++$nrProcessed if ($nrChanges) { ++$nrChanged } } Write-Host "Windows accounts: $nrProcessed accounts checked, $nrChanged changed" # Virtual groups $nrProcessed = 0 $nrChanged = 0 foreach ($group in $cfg.settings.access.virtGroups.entries) { $desc = "Virtual group '$($group.group)'" $nrChanges = CheckMountPoints $group $desc $nrChangesTotal += $nrChanges ++$nrProcessed if ($nrChanges) { ++$nrChanged } } Write-Host "Virtual groups: $nrProcessed groups checked, $nrChanged changed" # Virtual accounts $nrProcessed = 0 $nrChanged = 0 foreach ($account in $cfg.settings.access.virtAccounts.entries) { $desc = "Virtual account '$($account.virtAccount)'" $nrChanges = CheckMountPoints $account $desc $nrChangesTotal += $nrChanges ++$nrProcessed if ($nrChanges) { ++$nrChanged } } Write-Host "Virtual accounts: $nrProcessed accounts checked, $nrChanged changed" # Save and unlock settings if (-not $nrChangesTotal) { Write-Host "SSH Server instance $($instance.name): No mount points changed" } else { $plural = if ($nrChangesTotal -gt 1) { "s" } else { "" } Write-Host "SSH Server instance $($instance.name): Saving settings, $nrChangesTotal mount point$plural changed" $cfg.settings.Save() } } finally { $cfg.settings.Unlock() } } } Write-Host ""