Unpacking Software Livestream

Join our monthly Unpacking Software livestream to hear about the latest news, chat and opinion on packaging, software deployment and lifecycle management!

Learn More

Chocolatey Product Spotlight

Join the Chocolatey Team on our regular monthly stream where we put a spotlight on the most recent Chocolatey product releases. You'll have a chance to have your questions answered in a live Ask Me Anything format.

Learn More

Chocolatey Coding Livestream

Join us for the Chocolatey Coding Livestream, where members of our team dive into the heart of open source development by coding live on various Chocolatey projects. Tune in to witness real-time coding, ask questions, and gain insights into the world of package management. Don't miss this opportunity to engage with our team and contribute to the future of Chocolatey!

Learn More

Calling All Chocolatiers! Whipping Up Windows Automation with Chocolatey Central Management

Webinar from
Wednesday, 17 January 2024

We are delighted to announce the release of Chocolatey Central Management v0.12.0, featuring seamless Deployment Plan creation, time-saving duplications, insightful Group Details, an upgraded Dashboard, bug fixes, user interface polishing, and refined documentation. As an added bonus we'll have members of our Solutions Engineering team on-hand to dive into some interesting ways you can leverage the new features available!

Watch On-Demand
Chocolatey Community Coffee Break

Join the Chocolatey Team as we discuss all things Community, what we do, how you can get involved and answer your Chocolatey questions.

Watch The Replays
Chocolatey and Intune Overview

Webinar Replay from
Wednesday, 30 March 2022

At Chocolatey Software we strive for simple, and teaching others. Let us teach you just how simple it could be to keep your 3rd party applications updated across your devices, all with Intune!

Watch On-Demand
Chocolatey For Business. In Azure. In One Click.

Livestream from
Thursday, 9 June 2022

Join James and Josh to show you how you can get the Chocolatey For Business recommended infrastructure and workflow, created, in Azure, in around 20 minutes.

Watch On-Demand
The Future of Chocolatey CLI

Livestream from
Thursday, 04 August 2022

Join Paul and Gary to hear more about the plans for the Chocolatey CLI in the not so distant future. We'll talk about some cool new features, long term asks from Customers and Community and how you can get involved!

Watch On-Demand
Hacktoberfest Tuesdays 2022

Livestreams from
October 2022

For Hacktoberfest, Chocolatey ran a livestream every Tuesday! Re-watch Cory, James, Gary, and Rain as they share knowledge on how to contribute to open-source projects such as Chocolatey CLI.

Watch On-Demand

Downloads:

6,459,459

Downloads of v 0.0.15.20170611:

1,562

Last Update:

12 Jun 2017

Package Maintainer(s):

Software Author(s):

  • Microsoft

Tags:

openssh admin

Win32 OpenSSH (Universal Installer)

This is not the latest version of Win32 OpenSSH (Universal Installer) available.

  • 1
  • 2
  • 3

0.0.15.20170611 | Updated: 12 Jun 2017

Downloads:

6,459,459

Downloads of v 0.0.15.20170611:

1,562

Maintainer(s):

Software Author(s):

  • Microsoft

Tags:

openssh admin

Win32 OpenSSH (Universal Installer) 0.0.15.20170611

This is not the latest version of Win32 OpenSSH (Universal Installer) available.

Legal Disclaimer: Neither this package nor Chocolatey Software, Inc. are affiliated with or endorsed by Microsoft. The inclusion of Microsoft trademark(s), if any, upon this webpage is solely to identify Microsoft goods or services and not for commercial purposes.

  • 1
  • 2
  • 3

Some Checks Have Failed or Are Not Yet Complete

Not All Tests Have Passed


Validation Testing Passed


Verification Testing Passed

Details

Scan Testing Resulted in Flagged:

This package was submitted (and approved) prior to automated virus scanning integration into the package moderation processs.

We recommend clicking the "Details" link to make your own decision on installing this package.

Details
Learn More

Deployment Method: Individual Install, Upgrade, & Uninstall

To install Win32 OpenSSH (Universal Installer), run the following command from the command line or from PowerShell:

>

To upgrade Win32 OpenSSH (Universal Installer), run the following command from the command line or from PowerShell:

>

To uninstall Win32 OpenSSH (Universal Installer), run the following command from the command line or from PowerShell:

>

Deployment Method:

NOTE

This applies to both open source and commercial editions of Chocolatey.

1. Enter Your Internal Repository Url

(this should look similar to https://community.chocolatey.org/api/v2/)


2. Setup Your Environment

1. Ensure you are set for organizational deployment

Please see the organizational deployment guide

2. Get the package into your environment

  • Open Source or Commercial:
    • Proxy Repository - Create a proxy nuget repository on Nexus, Artifactory Pro, or a proxy Chocolatey repository on ProGet. Point your upstream to https://community.chocolatey.org/api/v2/. Packages cache on first access automatically. Make sure your choco clients are using your proxy repository as a source and NOT the default community repository. See source command for more information.
    • You can also just download the package and push it to a repository Download

3. Copy Your Script

choco upgrade openssh -y --source="'INTERNAL REPO URL'" --version="'0.0.15.20170611'" [other options]

See options you can pass to upgrade.

See best practices for scripting.

Add this to a PowerShell script or use a Batch script with tools and in places where you are calling directly to Chocolatey. If you are integrating, keep in mind enhanced exit codes.

If you do use a PowerShell script, use the following to ensure bad exit codes are shown as failures:


choco upgrade openssh -y --source="'INTERNAL REPO URL'" --version="'0.0.15.20170611'" 
$exitCode = $LASTEXITCODE

Write-Verbose "Exit code was $exitCode"
$validExitCodes = @(0, 1605, 1614, 1641, 3010)
if ($validExitCodes -contains $exitCode) {
  Exit 0
}

Exit $exitCode

- name: Install openssh
  win_chocolatey:
    name: openssh
    version: '0.0.15.20170611'
    source: INTERNAL REPO URL
    state: present

See docs at https://docs.ansible.com/ansible/latest/modules/win_chocolatey_module.html.


chocolatey_package 'openssh' do
  action    :install
  source   'INTERNAL REPO URL'
  version  '0.0.15.20170611'
end

See docs at https://docs.chef.io/resource_chocolatey_package.html.


cChocoPackageInstaller openssh
{
    Name     = "openssh"
    Version  = "0.0.15.20170611"
    Source   = "INTERNAL REPO URL"
}

Requires cChoco DSC Resource. See docs at https://github.com/chocolatey/cChoco.


package { 'openssh':
  ensure   => '0.0.15.20170611',
  provider => 'chocolatey',
  source   => 'INTERNAL REPO URL',
}

Requires Puppet Chocolatey Provider module. See docs at https://forge.puppet.com/puppetlabs/chocolatey.


4. If applicable - Chocolatey configuration/installation

See infrastructure management matrix for Chocolatey configuration elements and examples.

Package Approved

This package was approved as a trusted package on 12 Jun 2017.

Description

Open SSH tools for Windows.

*****************************************************************************
This package is actually a universal installer that can install in any scenario - including without Chocolatey.
Read here for more information: https://github.com/DarwinJS/ChocoPackages/blob/master/openssh/readme.md
*****************************************************************************

CloudyWindows.com Utility Scripts:
* Set-SSHKeyPermissions.ps1

This package supports the following parameters:

-params '"/SSHServerFeature"' (Install and Uninstall)
Also install sshd Windows Service - including opening port 22.
If this parameter is not included on an upgrade or uninstall and
the sshd server is installed - an error is generated. You must
use this switch to indicate you have made preparations for the
sshd service to be interrupted or removed.

-params '"/SSHAgentFeature"'
Installs SSH Agent Service even if SSHD Server is not being installed.
Requires admin rights to configure service.
This option is automatically set when /SSHServerFeature is used.

-params '"/SSHServerFeature /SSHServerPort:3834"'
Allows the setup of the SSH server on an alternate port - sometimes done for security or to avoid conflicts with an existing service on port 22.

-params '"/OverWriteSSHDConf"'
Introduced in Version: 0.0.9.20170311
By default an existing sshd_conf file will not be overwritten (previous packaging versions always overwrote)
Use this switch to overwrite an existing sshd_conf with the one from the current install media

-params '"/SSHLogLevel:VERBOSE"'
Introduced in Version: 0.0.9.20170311
Allows the setup of the SSH logging level.
Valid Options: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, DEBUG3
On a fresh install LogLevel is set to QUIET

-params '"/TERM:xterm-new"'
Introduced in Version: 0.0.14.0
Allows the initial setup and subsequent update of the TERM system environment variable.
On a fresh install TERM is set to xterm whether or not this switch is used.

-params '"/DisableKeyPermissionsReset"'
Introduced in Version: 0.0.15.0
As of 0.0.13.0 new key permissions are required for ssh keys. By default this installer
reasserts these permissions whenever run. Used this switch if you do not want the installation
to attempt to manage key permissions. The utility script will still be installed and available
if you need to use it later to fix up permissions.

-params '"/SSHServerFeature /DeleteServerKeysAfterInstalled"'
Also install sshd Windows Service - including opening port 22 and
it with Key Based Authentication (reboot required before active)
Server keys are deleted after added to the ssh-agent (you will not have an opportunity to copy them)

-params '"/SSHServerFeature /DeleteConfigAndServerKeys"' (Uninstall)
By default an uninstall does not remove config files nor server keys.

-params '"/UseNTRights"'
By default the install uses PowerShell code that works on operating systems that cannot run the 32-bit ntrights.exe (Nano, Server Core w/out WOW64).
If this code does not work for you, you can use this switch to invoke the 32-bit ntrights.exe


tools\7z.dll
md5: 9943B3BCB2CA91CCBEF2D96682CECB79 | sha1: D467F1F7A8407D1650060C8FE3DC6A0CCFF4D409 | sha256: 7F47382791A5264EED7310706E105C1CFA0E727359102F14933D4927BD296640 | sha512: D724BA334CEC2E3D69BBC93FEA635377EDC941962E2FFBE8246C2ADA80D445DEAB7F3BB5A18FCEAE295428C5B47CE42F3CD56F94AB9F170560DDDED167BE2995
tools\7z.exe
md5: 506E5B371882A5A62B669F04CE04DBA8 | sha1: 7447EB123655792FEDE586AD049AC737EFFA9E6C | sha256: BB783A594067DB5CB4E43030D9E6928636555A9CE6AA3533532731975094230A | sha512: 7F367D22B95E14AF8BDA3BE1354A4A54EDFDA283700D086878FEA72B349E64B497F2D241AE31E0B2B0C56957D3A39299E51E09B0D67D2C6201AE20033555212E
tools\7z.exe.ignore
 
tools\AddAccountToAssignPrimaryToken.ps1
param($accountToAdd)
#written by Ingo Karstein, http://blog.karstein-consulting.com
#  v1.0, 01/03/2014

## <--- Configure here

if( [string]::IsNullOrEmpty($accountToAdd) ) {
	Write-Host "no account specified"
	exit
}

## ---> End of Config

$sidstr = $null
try {
	$ntprincipal = new-object System.Security.Principal.NTAccount "$accountToAdd"
	$sid = $ntprincipal.Translate([System.Security.Principal.SecurityIdentifier])
	$sidstr = $sid.Value.ToString()
} catch {
	$sidstr = $null
}

Write-Host "Account: $($accountToAdd)" -ForegroundColor DarkCyan

if( [string]::IsNullOrEmpty($sidstr) ) {
	Write-Host "Account not found!" -ForegroundColor Red
	exit -1
}

Write-Host "Account SID: $($sidstr)" -ForegroundColor DarkCyan

$tmp = [System.IO.Path]::GetTempFileName()

Write-Host "Export current Local Security Policy" -ForegroundColor DarkCyan
secedit.exe /export /cfg "$($tmp)"

$c = Get-Content -Path $tmp

$currentSetting = ""

foreach($s in $c) {
	if( $s -like "SeAssignPrimaryTokenPrivilege*") {
		$x = $s.split("=",[System.StringSplitOptions]::RemoveEmptyEntries)
		$currentSetting = $x[1].Trim()
	}
}

if( $currentSetting -notlike "*$($sidstr)*" ) {
	Write-Host "Modify Setting ""Replace a process level token""" -ForegroundColor DarkCyan

	if( [string]::IsNullOrEmpty($currentSetting) ) {
		$currentSetting = "*$($sidstr)"
	} else {
		$currentSetting = "*$($sidstr),$($currentSetting)"
	}

	Write-Host "$currentSetting"

	$outfile = @"
[Unicode]
Unicode=yes
[Version]
signature="`$CHICAGO`$"
Revision=1
[Privilege Rights]
SeAssignPrimaryTokenPrivilege = $($currentSetting)
"@

	$tmp2 = [System.IO.Path]::GetTempFileName()


	Write-Host "Import new settings to Local Security Policy" -ForegroundColor DarkCyan
	$outfile | Set-Content -Path $tmp2 -Encoding Unicode -Force

	#notepad.exe $tmp2
	Push-Location (Split-Path $tmp2)

	try {
		secedit.exe /configure /db "secedit.sdb" /cfg "$($tmp2)" /areas USER_RIGHTS
		#write-host "secedit.exe /configure /db ""secedit.sdb"" /cfg ""$($tmp2)"" /areas USER_RIGHTS "
	} finally {
		Pop-Location
	}
} else {
	Write-Host "NO ACTIONS REQUIRED! Account already in ""Replace a process level token""" -ForegroundColor DarkCyan
}

Write-Host "Done." -ForegroundColor DarkCyan
tools\AddAccountToLogonAsAService.ps1
param($accountToAdd)
#written by Ingo Karstein, http://blog.karstein-consulting.com
#  v1.0, 01/03/2014

## <--- Configure here

if( [string]::IsNullOrEmpty($accountToAdd) ) {
	Write-Host "no account specified"
	exit
}

## ---> End of Config

$sidstr = $null
try {
	$ntprincipal = new-object System.Security.Principal.NTAccount "$accountToAdd"
	$sid = $ntprincipal.Translate([System.Security.Principal.SecurityIdentifier])
	$sidstr = $sid.Value.ToString()
} catch {
	$sidstr = $null
}

Write-Host "Account: $($accountToAdd)" -ForegroundColor DarkCyan

if( [string]::IsNullOrEmpty($sidstr) ) {
	Write-Host "Account not found!" -ForegroundColor Red
	exit -1
}

Write-Host "Account SID: $($sidstr)" -ForegroundColor DarkCyan

$tmp = [System.IO.Path]::GetTempFileName()

Write-Host "Export current Local Security Policy" -ForegroundColor DarkCyan
secedit.exe /export /cfg "$($tmp)"

$c = Get-Content -Path $tmp

$currentSetting = ""

foreach($s in $c) {
	if( $s -like "SeServiceLogonRight*") {
		$x = $s.split("=",[System.StringSplitOptions]::RemoveEmptyEntries)
		$currentSetting = $x[1].Trim()
	}
}

if( $currentSetting -notlike "*$($sidstr)*" ) {
	Write-Host "Modify Setting ""Logon as a Service""" -ForegroundColor DarkCyan

	if( [string]::IsNullOrEmpty($currentSetting) ) {
		$currentSetting = "*$($sidstr)"
	} else {
		$currentSetting = "*$($sidstr),$($currentSetting)"
	}

	Write-Host "$currentSetting"

	$outfile = @"
[Unicode]
Unicode=yes
[Version]
signature="`$CHICAGO`$"
Revision=1
[Privilege Rights]
SeServiceLogonRight = $($currentSetting)
"@

	$tmp2 = [System.IO.Path]::GetTempFileName()


	Write-Host "Import new settings to Local Security Policy" -ForegroundColor DarkCyan
	$outfile | Set-Content -Path $tmp2 -Encoding Unicode -Force

	#notepad.exe $tmp2
	Push-Location (Split-Path $tmp2)

	try {
		secedit.exe /configure /db "secedit.sdb" /cfg "$($tmp2)" /areas USER_RIGHTS
		#write-host "secedit.exe /configure /db ""secedit.sdb"" /cfg ""$($tmp2)"" /areas USER_RIGHTS "
	} finally {
		Pop-Location
	}
} else {
	Write-Host "NO ACTIONS REQUIRED! Account already in ""Logon as a Service""" -ForegroundColor DarkCyan
}

Write-Host "Done." -ForegroundColor DarkCyan
tools\barebonesinstaller.ps1
<#
.SYNOPSIS
Enables installing SSH even when your system does not have WOW64 or Chocolatey.
.DESCRIPTION
This script enables installing  SSH even when your system does NOT have:
  [1] Chocolatey installed
  [2] WOW64 installed
  [3] .NET Core (Nano)

The use cases are Server Nano and Server Core without WOW64 installed.

To use barebonesinstaller.ps1, expand the .nupkg that this file is contained in
and then place the \tools folder on the target system.

To push tools folder to Nano use 'Copy-Item -tosession $sessionvariable tools c:\tools -recurse'
.PARAMETER SSHServerFeature
Include SSH Server Feature.
.PARAMETER SSHServerPort
The port that SSHD Server should listen on.
.PARAMETER DeleteServerKeysAfterInstalled
Delete server private keys after they have been secured
.PARAMETER DeleteConfigAndServerKeys
Delete server private keys and configuration upon uninstall.
.PARAMETER Uninstall
Uninstall (default is to install)
.PARAMETER DisableKeyPermissionsReset
By default the install runs a custom utility script called "Reset-SSHKeyPermissions.ps1". This switch disables that functionality.
.EXAMPLE
.\barebonesinstaller.ps1 -SSHServerFeature
.EXAMPLE
.\barebonesinstaller.ps1 -SSHServerFeature -Uninstall
#>

Param (
  [switch]$SSHServerFeature,
  [string]$SSHServerPort='22',
  [switch]$DeleteServerKeysAfterInstalled,
  [switch]$DeleteConfigAndServerKeys,
  [switch]$UseNTRights,
  [switch]$Uninstall,
  [switch]$OverWriteSSHDConf,
  [string]$SSHLogLevel,
  [switch]$ReleaseSSHLSAForUpgrade,
  [string]$TERM,
  [switch]$DisableKeyPermissionsReset
  )

Write-Output "Configuring on Port $SSHServerPort"

cd "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"

If (!$Uninstall)
{
  . ".\chocolateyinstall.ps1"
}
Else
{
  . ".\chocolateyuninstall.ps1"
}
tools\chocolateyinstall.ps1

<#
ATTENTION: This code is used extensively to run under PowerShell 2.0 to update 
images from RTM / SP1 source for Windows 7 and Server 2008 R2.  It is also
used under Powershell Core to add OpenSSH to Nano.  Test all enhancements and 
fixes under these two specialty cases (speciality for Chocolatey packagers who are 
likely up to the latest version on everything PowerShell).
#>


$ErrorActionPreference = 'Stop'; # stop on all errors

$ProductName = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'ProductName').ProductName
$EditionId = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'EditionID').EditionId

Write-Output "Running on: $ProductName, ($EditionId)"

If ($EditionId -ilike '*Nano*')
{$RunningOnNano = $True}

If (Test-Path variable:shimgen)
{$RunningUnderChocolatey = $True}
Else
{  Write-Output "Running Without Chocolatey"}

$toolsDir   = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
$OSBits = ([System.IntPtr]::Size * 8) #Get-ProcessorBits

#On 64-bit, always favor 64-bit Program Files no matter what our execution is now (works back past XP / Server 2003)
If ($env:ProgramFiles.contains('x86'))
{
  $PF = $env:ProgramFiles.replace(' (x86)','')
}
Else
{
  $PF = $env:ProgramFiles
}

If (Test-Path "$env:windir\sysnative")
{ #We are running in a 32-bit process under 64-bit Windows
  $sys32dir = "$env:windir\sysnative"
}
Else
{ #We are on a 32-bit OS, or 64-bit proc on 64-bit OS
  $sys32dir = "$env:windir\system32"
}
$filename = "$toolsdir\OpenSSH-Win$($OSBits).zip"
#$TargetFolder = "$PF\OpenSSH"
#$TargetFolderOld = "$PF\OpenSSH-Win$($OSBits)"
$TargetFolder = "$PF\OpenSSH-Win$($OSBits)"
$ExtractFolder = "$env:temp\OpenSSHTemp"
$SSHLSAFeaturesDisabled = $True
$TERMDefault = 'xterm'
$sshlsaisLocked = $false

$packageArgs = @{
  packageName   = 'openssh'
  unziplocation = "$ExtractFolder"
  fileType      = 'EXE_MSI_OR_MSU' #only one of these: exe, msi, msu

  checksum      = 'E39CB40DAA37B493F42A77DDC7B57A4E7674997E'
  checksumType  = 'SHA1'
  checksum64    = 'B797E0DB1D4D2702F6BEE49FD178E6E94596C290'
  checksumType64= 'SHA1'
}

If ($RunningUnderChocolatey)
{
  # Default the values before reading params
  $SSHServerFeature = $false
  $KeyBasedAuthenticationFeature = $false
  $DeleteServerKeysAfterInstalled = $false
  $UseNTRights = $false
  $SSHServerPort = '22'
  $DisableKeyPermissionsReset = $False

  $arguments = @{};
  $packageParameters = $env:chocolateyPackageParameters
}

$OpeningMessage = @"

************************************************************************************
************************************************************************************
This package is a Universal Installer and can ALSO install Win32-OpenSSH on 
Nano, Server Core, Docker Containers and more WITHOUT using Chocolatey.

See the following for more details:
https://github.com/DarwinJS/ChocoPackages/blob/master/openssh/readme.md
************************************************************************************
************************************************************************************

"@

Write-Output $OpeningMessage

# Now parse the packageParameters using good old regular expression
if ($packageParameters) {
    $match_pattern = "\/(?<option>([a-zA-Z]+)):(?<value>([`"'])?([a-zA-Z0-9- _\\:\.]+)([`"'])?)|\/(?<option>([a-zA-Z]+))"
    #"
    $option_name = 'option'
    $value_name = 'value'

    if ($packageParameters -match $match_pattern ){
        $results = $packageParameters | Select-String $match_pattern -AllMatches
        $results.matches | % {
          $arguments.Add(
              $_.Groups[$option_name].Value.Trim(),
              $_.Groups[$value_name].Value.Trim())
      }
    }
    else
    {
      throw "Package Parameters were found but were invalid (REGEX Failure)"
    }

    if ($arguments.ContainsKey("SSHAgentFeature")) {
        Write-Host "/SSHAgentFeature was used, including SSH Agent Service."
        $SSHAgentFeature = $true
    }

    if ($arguments.ContainsKey("SSHServerFeature")) {
        Write-Host "/SSHServerFeature was used, including SSH Server Feature."
        $SSHServerFeature = $true
    }

    if ($arguments.ContainsKey("DisableKeyPermissionsReset")) {
        Write-Host "/DisableKeyPermissionsReset was used, will not reset key permissions."
        $DisableKeyPermissionsReset = $true
    }

    if ($arguments.ContainsKey("OverWriteSSHDConf")) {
        Write-Host "/OverWriteSSHDConf was used, will overwrite any existing sshd_conf with one from install media."
        $OverWriteSSHDConf = $true
    }

    if ($arguments.ContainsKey("SSHServerPort")) {
        $SSHServerPort = $arguments.Get_Item("SSHServerPort")
        Write-Host "/SSHServerPort was used, attempting to use SSHD listening port $SSHServerPort."
        If (!$SSHServerFeature)
        {
          Write-Host "You forgot to specify /SSHServerFeature with /SSHServerPort, autofixing for you, enabling /SSHServerFeature"
          $SSHServerFeature = $true
        }
    }

    if ($arguments.ContainsKey("SSHLogLevel")) {

      $ValidLogSettings = @('QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE', 'DEBUG', 'DEBUG1', 'DEBUG2','DEBUG3')
      $SSHLogLevel = $arguments.Get_Item("SSHLogLevel").toupper()
      If ($ValidLogSettings -inotcontains $SSHLogLevel)
      {Throw "$SSHLogLevel is not one of the valid values: $(($ValidLogSettings -join ' ') | out-string)"}
      Write-Host "/SSHLogLevel was used, setting LogLevel in sshd_conf to $SSHLogLevel"

    }
    Else
    {
      $SSHLogLevel = $null
    }

    if ($arguments.ContainsKey("TERM")) {
      $TERM = $arguments.Get_Item("TERM")
      Write-Host "/TERM was used, setting system TERM environment variable to $TERM"
      $TERMSwitchUsed = $True
    }
    Else
    {
      $TERM = 'xterm'
      Write-Host "Defaulting system TERM environment variable to $TERM"
    }
<#
    if ($arguments.ContainsKey("ReleaseSSHLSAForUpgrade")) {
        $ReleaseSSHLSAForUpgrade = $true
    }
#>
    if ($arguments.ContainsKey("UseNTRights")) {
        Write-Host "Using ntrights.exe to set service permissions (will not work, but generate warning if WOW64 is not present on 64-bit machines)"
        $UseNTRights = $true
    }

    if ($arguments.ContainsKey("DeleteServerKeysAfterInstalled")) {
        Write-Host "Deleting server private keys after they have been secured."
        $DeleteServerKeysAfterInstalled = $true
    }

    if ($arguments.ContainsKey("KeyBasedAuthenticationFeature")) {
        Write-Host "Including LSA DLL Feature."
        $KeyBasedAuthenticationFeature = $true
        If (!$SSHServerFeature)
        {
          Write-Warning "KeyBasedAuthenticationFeature was specified, but is only value when SSHServerFeature is specified, ignoring..."
        }
    }

} else {
    Write-Debug "No Package Parameters Passed in";
}

Function CheckServicePath ($ServiceEXE,$FolderToCheck)
{
  #The modern way:
  #Return ([bool]((Get-WmiObject win32_service | ?{$_.Name -ilike "*$ServiceEXE*"} | select -expand PathName) -ilike "*$FolderToCheck*"))
  #The NANO TP5 Compatible Way:
  Return ([bool](@(wmic service | ?{$_ -ilike "*$ServiceEXE*"}) -ilike "*$FolderToCheck*"))
}

#Extract Files Early
If ($RunningUnderChocolatey)
{
  If (Test-Path $ExtractFolder)
  {
    Remove-Item $ExtractFolder -Recurse -Force
  }
  Get-ChocolateyUnzip "$filename" $ExtractFolder
}
Else
{
  If (Test-Path "$toolsdir\7z.exe")
  {
    #covers nano
    cd $toolsdir
    start-process .\7z.exe -argumentlist "x `"$filename`" -o`"$ExtractFolder`" -aoa" -nonewwindow -wait
  }
  Else
  {
    Throw "You need a copy of 7z.exe next to this script for this operating system.  You can get a copy at 7-zip.org"
  }
}

If (($SSHLSAFeaturesDisabled) -AND (Test-Path "$env:windir\system32\ssh-lsa.dll"))
{
  try
  {
    Remove-Item "$sys32dir\ssh-lsa.dll"
    Write-warning "ssh-lsa.dll was deleted as it is no longer needed."
  }
  catch
  {
    $sshlsaisLocked = $true
    Write-warning "ssh-lsa.dll is no longer required for ssh functionality, releasing the existing ssh-lsa.dll from lsass.exe."
    Write-warning "It can be manually delete after a reboot or it will be automatically removed the next time you upgrade openssh with this script."
    Write-warning "You must reboot to release ssh-lsa.dll"
  
    $AuthpkgToRemove = 'ssh-lsa'
    foreach ($authpackage in (get-item 'Registry::HKLM\System\CurrentControlSet\Control\Lsa').getvalue("authentication packages"))
    {
    If ($authpackage)
      {
        If ($authpackage -ine "$AuthpkgToRemove")
        {
          [string[]]$Newauthpackages += "$authpackage"
        }
      }
    }
    Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\" "Authentication Packages" $Newauthpackages
  }
}

If (!$SSHLSAFeaturesDisabled)
{
$SSHLsaNeedsUpdating = $false
If (Test-Path "$env:windir\system32\ssh-lsa.dll")
{
  <#For future if file version number only updates when code updates
  PSH 2.0 compatible, should handle ssh-lsa.dll versions that do not have a version resource as well
  #handles when ssh-lsa.dll code is not actually changed, but version is updated (checking size does not)
  $currentsshlsaversion = get-command $env:windir\system32\ssh-lsa.dll -erroraction SilentlyContinue | select -expand FileVersionInfo | select -expand FileVersion
  $newsshlsaversion = get-command $TargetFolder\ssh-lsa.dll | select -expand FileVersionInfo | select -expand FileVersion
  
  If ([version]$currentsshlsaversion -lt [version]$newsshlsaversion)
  { 
    $SSHLsaNeedsUpdating = $true
  }
  #>
  Write-Output "Assessing whether ssh-lsa.dll needs updating.  This is done based on FILE SIZE" 
  Write-Output "because the version is revised on each update whether the code changes"
  Write-Output " or not - yet the dll requires two reboots to update."
  If (((get-item $env:windir\system32\ssh-lsa.dll).length) -ne ((get-item "$ExtractFolder\OpenSSH-Win$($OSBits)\ssh-lsa.dll").length))
  {
    $SSHLsaNeedsUpdating = $true
    Write-Output "ssh-lsa.dll file size has changed, an update is required."
  }
  else 
  {
    Write-Output "ssh-lsa.dll file size has NOT changed, an update is NOT required."
    Write-Warning "IMPORTANT: the ssh-lsa.dll file version will not change to the newer version number, but does not need updating."
    Write-Warning "  This approach is used by the Chocolatey package because it takes two reboots to update ssh-lsa.dll."
  }
}
Else
{
  $SSHLsaNeedsInitialCopy = $true
}

If ($SSHLsaNeedsUpdating)
{
  try
  {
    Remove-Item "$sys32dir\ssh-lsa.dll"
  }
  catch
  {
    #If ($_.exception -ilike "*used by another process*")
    #{
       $sshlsaisLocked = $true
    #}
  }

  If ($sshlsaisLocked)
  {
    If ($ReleaseSSHLSAForUpgrade)
    {
      $AuthpkgToRemove = 'ssh-lsa'
      foreach ($authpackage in (get-item 'Registry::HKLM\System\CurrentControlSet\Control\Lsa').getvalue("authentication packages"))
      {
      If ($authpackage)
        {
          If ($authpackage -ine "$AuthpkgToRemove")
          {
            [string[]]$Newauthpackages += "$authpackage"
          }
        }
      }
      Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\" "Authentication Packages" $Newauthpackages
      Write-Warning "ATTENTION:"
      Write-Warning "   [a] ssh-lsa.dll needs to be updated" 
      Write-Warning "   [b] and it was found to be locked"
      Write-Warning "   [c] and the switch /ReleaseSSHLSAForUpgrade was used."
      Write-Warning "   ssh-lsa has been deconfigured from loading under lsass.exe, you"
      Write-Warning "   must now reboot to release it from lsass.exe and then re-run this"
      Write-Warning "   package with the -force switch, after which you will need to reboot again to install the new version."
      Write-Warning ""
      Write-Warning "CRITCAL: AT THIS POINT KEY BASED AUTHENTICATION HAS BE DE-CONFIGURED AND WILL STOP WORKING"
      Write-Warning "    AT THE NEXT REBOOT.  TO RESTORE IT YOU MUST REBOOT AND RERUN THIS PACKAGE."
      Write-Warning ""
      Write-Warning "   Full Help here: https://github.com/DarwinJS/ChocoPackages/blob/master/openssh/readme.md"
      Exit 0
    }
    Else
    {
      Write-Warning ""
      Write-Warning "EXITING - CRITICAL:"
      Write-Warning "   This package includes an updated version of ssh-lsa.dll compared to the one you have on"
      Write-Warning "    your system.  ssh-lsa.dll on your system is currently locked by the critical system "
      Write-Warning "   process lsass.exe. (Terminating it will blue screen Windows) This situation will not be "
      Write-Warning "   resolved by this run, if you wish to resolve it."
      Write-Warning ""
      Write-Warning "TWO OPTIONS FOR UPDATING:"
      Write-Warning ""
      Write-Warning "   OPTION 1: Re-run this package with the switch /ReleaseSSHLSAForUpgrade"
      Write-Warning "   this package will release ssh-lsa.dll and exit.  Then you reboot, re-run this package"
      Write-Warning "   with choco's -force switch and reboot again."
      Write-Warning "   This option preserves your ssh configuration and server keys."
      Write-Warning ""
      Write-Warning "   OPTION 2: Uninstall this package with the command line "
      Write-Warning "   'choco uninstall -y openssh -params '`"/SSHServerFeature /DeleteConfigurationAndServerKeys`"'"
      Write-Warning "   Then you reboot, re-run this package.  One more reboot ensures the new version of"
      Write-Warning "   ssh-lsa.dll is active."
      Write-Warning "   This option DOES NOT preserve your ssh configuration and server keys."
      Write-Warning ""
      Write-Warning " PLEASE NOTE: STANDARD WINDOWS PENDINGFILERENAME SUPPORT DOES NOT WORK DUE TO HOW EARLY "
      Write-Warning "     LSASS.EXE STARTS IN THE BOOT PROCESS"
      Write-Warning ""
      Write-Warning "   Full Help here: https://github.com/DarwinJS/ChocoPackages/blob/master/openssh/readme.md"
      Throw "Special procedures are required to successfully update ssh-lsa.dll (key based authentication support), please see about chocolatey log statements for procedures."
    }
  }
}
}

If ($SSHServerFeature)
{  #Check if anything is already listening on port $SSHServerPort, which is not a previous version of this software.
  Write-Host "/SSHAgentFeature is also automatically enabled when using /SSHServerFeature."
  $SSHAgentFeature = $true
  $AtLeastOneSSHDPortListenerIsNotUs = $False
  Write-Output "Probing for possible conflicts with SSHD server to be configured on port $SSHServerPort ..."
  . "$toolsdir\Get-NetStat.ps1"
  $procslisteningonRequestedSSHDPort = @(Get-Netstat -GetProcessDetails -FilterOnPort $SSHServerPort)
  If ((checkservicepath 'svchost.exe -k SshBrokerGroup' 'Part of Microsoft SSH Server for Windows') -AND (checkservicepath 'svchost.exe -k SshProxyGroup' 'Part of Microsoft SSH Server for Windows'))
  {
    Write-Warning "  > Detected that Developer Mode SSH is present (Probably due to enabling Windows 10 Developer Mode)"
    $DeveloperModeSSHIsPresent = $True
  }

  If ($procslisteningonRequestedSSHDPort.count -ge 1)
  {
    ForEach ($proconRequestedSSHDPort in $procslisteningonRequestedSSHDPort)
    {
      Write-output "  > Checking $($proconRequestedSSHDPort.Localaddressprocesspath) against path $TargetFolder"
      If ("$($proconRequestedSSHDPort.Localaddressprocesspath)" -ilike "*$TargetFolder*")
      {
        Write-Output "  > Found a previous version of Win32-OpenSSH installed by this package on Port $SSHServerPort."
      }
      Else
      {
        $AtLeastOneSSHDPortListenerIsNotUs = $True
        Write-Warning "  > Found something listening on Port $SSHServerPort that was not installed by this package."
        Write-Warning "      $($proconRequestedSSHDPort.LocalAddressProcessPath) is listening on Port $SSHServerPort"
        $ProcessOccupyingPort = "$($proconRequestedSSHDPort.LocalAddressProcessPath)"
      }
    }
  }

  If ($AtLeastOneSSHDPortListenerIsNotUs)
  {
  $errorMessagePort = @"
"$ProcessOccupyingPort" is listening on port $SSHServerPort and you have not specified a different listening port (list above) using the /SSHServerPort parameter.
Please either deconfigure or deinstall whatever is running on Port $SSHServerPort and try again OR specify a different port for this SSHD Server using the /SSHServerPort package parameter.
If you see the message 'Detected that Developer Mode SSH is present' above, you may be able to simply disable the services 'SSHBroker' and 'SSHProxy'
"@
  Throw $errorMessagePort
  }
}

$SSHServiceInstanceExistsAndIsOurs = CheckServicePath 'sshd.exe' "$TargetFolder"
$SSHAGENTServiceInstanceExistsAndIsOurs = CheckServicePath 'ssh-agent.exe' "$TargetFolder"

If ($SSHServerFeature -AND (!$SSHServiceInstanceExistsAndIsOurs) -AND ([bool](Get-Service sshd -ErrorAction SilentlyContinue)))
{
  $ExistingSSHDInstancePath = get-itemproperty hklm:\system\currentcontrolset\services\* | where {($_.ImagePath -ilike '*sshd.exe*')} | Select -expand ImagePath
  Throw "You have requested that the SSHD service be installed, but this system appears to have an instance of an SSHD service configured for another folder ($ExistingSSHDInstancePath).  You can remove the package switch /SSHServerFeature to install just the client tools, or you will need to remove that instance of SSHD to use the one that comes with this package."
}

If ((!$SSHServerFeature) -AND $SSHServiceInstanceExistsAndIsOurs)
{
  Throw "There is a configured instance of the SSHD service, please specify the /SSHServerFeature to confirm it is OK to shutdown and upgrade the SSHD service at this time."
}

If ([bool](get-process ssh -erroraction silentlycontinue | where {$_.Path -ilike "*$TargetFolder*"}))
{
  Throw "It appears you have instances of ssh.exe (client) running from the folder this package installs to, please terminate them and try again."
}

If ((Test-Path $TargetFolder) -AND (@(dir "$TargetFolder\*.exe").count -gt 0)) 
{
  Write-Output "`r`nCURRENT VERSIONS OF SSH EXES:"
    Write-Output "$(dir "$TargetFolder\*.exe"| select -expand fullname | get-command | select -expand fileversioninfo | ft filename, fileversion -auto | out-string)"
}

If (Test-Path "$env:windir\system32\ssh-lsa.dll") 
{
  Write-Output "`r`nCURRENT VERSION OF SSH-LSA.DLL:"
  Write-Output "$(get-command "$env:windir\system32\ssh-lsa.dll" | select -expand fileversioninfo | ft filename, fileversion -auto | out-string)"
}

If ($SSHServiceInstanceExistsAndIsOurs -AND ([bool](Get-Service SSHD -ErrorAction SilentlyContinue | where {$_.Status -ieq 'Running'})))
{
    #Shutdown and unregister service for upgrade
    stop-service sshd -Force
    Stop-Service SSH-Agent -Force
    Start-Sleep -seconds 3
    If (([bool](Get-Service SSHD | where {$_.Status -ieq 'Running'})))
    {
      Throw "Could not stop the SSHD service, please stop manually and retry this package."
    }
    If ($SSHAGENTServiceInstanceExistsAndIsOurs)
    {
      stop-service ssh-agent -Force
      Start-Sleep -seconds 3
      If (([bool](Get-Service ssh-agent | where {$_.Status -ieq 'Running'})))
      {
        Throw "Could not stop the ssh-agent service, please stop manually and retry this package."
      }
    }
}

If ($SSHServiceInstanceExistsAndIsOurs)
{
  Write-output "Stopping SSHD Service for upgrade..."
  Stop-Service sshd
  sc.exe delete sshd | out-null
}
If ($SSHAGENTServiceInstanceExistsAndIsOurs)
{
  Write-output "Stopping SSH-Agent Service for upgrade..."
  Stop-Service ssh-agent -erroraction silentlycontinue
  sc.exe delete ssh-agent | out-null
}

If ($OSBits -eq 64)
{
  $SourceZipChecksum = $packageargs.checksum64
  $SourceZipChecksumType = $packageargs.checksumType64
}
Else
{
  $SourceZipChecksum = $packageargs.checksum
  $SourceZipChecksumType = $packageargs.checksumType
}

If ([bool](get-command get-filehash -ea silentlycontinue))
{
  If ((Get-FileHash $filename -Algorithm $SourceZipChecksumType).Hash -eq $SourceZipChecksum)
  {
    Write-Output "Hashes for internal source match"
  }
  Else
  {
    throw "Checksums for internal source do not match - something is wrong."
  }
}
Else
{
  Write-Output "Source files are internal to the package, checksums are not required nor checked."
}

$ExcludeParams = @{}
If ((Test-Path "$TargetFolder\sshd_config") -AND !($OverWriteSSHDConf))
{
  Write-Output "sshd_config already exists, not overwriting"
  $ExcludeParams.Add("Exclude","sshd_config")
}

Copy-Item "$ExtractFolder\*" "$PF" @ExcludeParams -Force -Recurse -Passthru -ErrorAction Stop
#Fixed version of module
Write-Host "Updating OpenSSHUtils PowerShell Module to Latest"
Copy-Item "$toolsdir\OpenSSHUtils.ps*" "$TargetFolder" -Force -PassThru -ErrorAction Stop
Copy-Item "$toolsdir\Fix*FilePermissions.ps1" "$TargetFolder" -Force -PassThru -ErrorAction Stop

Remove-Item "$ExtractFolder" -Force -Recurse

If ($RunningUnderChocolatey)
{
  Install-ChocolateyPath "$TargetFolder" 'Machine'
}
Else
{
  $PathToAdd = $TargetFolder
  $ExistingPathArray = @(((Get-ItemProperty 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' | select -expand path).split(';')))
  if (($ExistingPathArray -inotcontains $PathToAdd) -AND ($ExistingPathArray -inotcontains "$PathToAdd\"))
  {
    $Newpath = $ExistingPathArray + @("$PathToAdd")
    $AssembledNewPath = ($newpath -join(';')).trimend(';')
    Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name 'PATH' -Value "$AssembledNewPath"
  }
}
If ($env:Path -inotlike "*$TargetFolder*")
{
  $env:path += ";$TargetFolder"
}

$ExistingTermValue = $null
$ExistingTermValue = (get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -EA SilentlyContinue | Select -Expand TERM -EA SilentlyContinue)

If (!$TERM) {$TERM = $TERMDefault}

If ((!$ExistingTermValue) -OR ($ExistingTermValue -ine $TERM))
{ 
  Write-Host "Updating machine environment variable TERM from `"$ExistingTermValue`" to `"$TERM`""
  Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name 'TERM' -Value "$TERM"
}

If ($SSHAgentFeature)
{
  New-Service -Name ssh-agent -BinaryPathName "$TargetFolder\ssh-agent.exe" -Description "SSH Agent" -StartupType Automatic | Out-Null
  cmd.exe /c 'sc.exe sdset ssh-agent D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;RP;;;AU)'

  Start-Service ssh-agent

  Start-Sleep -seconds 3

  If (!$UseNTRights)
  {
    #The code in this .PS1 has been tested on Nano - the hardest case to date for setting special privileges in script
    . "$toolsdir\AddAccountToLogonAsAService.ps1" -AccountToAdd "NT SERVICE\SSH-Agent"
  }
  Else
  {
    If (($OSBits -eq 64) -and (!(Test-Path "$env:windir\syswow64")))
    {
      Write-Warning "This 64-bit system does not have the WOW64 subsystem installed, please manually grant the right SeLogonAsAService to `"NT SERVICE\SSHD`"."
      Write-Warning "OR try again WITHOUT the /UseNTRights switch."
    }
    Else
    {
      write-output "Using ntrights.exe to grant logon as service."
      Start-Process "$TargetFolder\ntrights.exe" -ArgumentList "-u `"NT SERVICE\SSH-Agent`" +r SeAssignPrimaryTokenPrivilege"
    }
  }
}

If ($SSHServerFeature)
{
  Write-Warning "You have specified SSHServerFeature - this machine is being configured as an SSH Server including opening port $SSHServerPort."

    If (!$SSHLSAFeaturesDisabled)
    {
      Write-Warning "You have specified SSHServerFeature - a new lsa provider will be installed."
      If ($SSHLsaNeedsUpdating -OR $SSHLsaNeedsInitialCopy)
      {
        . "$toolsdir\fileinuseutils.ps1"
        $CopyLSAResult = Copy-FileEvenIfLocked "$TargetFolder\ssh-lsa.dll" "$sys32dir\ssh-lsa.dll"
      }

      #Don't destroy other values
      $key = get-item 'Registry::HKLM\System\CurrentControlSet\Control\Lsa'
      $values = $key.GetValue("Authentication Packages")
      If (!($Values -contains 'ssh-lsa'))
      {
        Write-Output "Adding ssh-lsa to authentication packages..."
        $values += 'ssh-lsa'
        Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\" "Authentication Packages" $values
      }
      Else
      {
        Write-Output "ssh-lsa already configured in authentication packages..."
      }
    }

  If((Test-Path "$TargetFolder\sshd_config"))
  {
    #(Get-Content "$TargetFolder\sshd_config") -replace '#LogLevel INFO', 'LogLevel QUIET' | Set-Content "$TargetFolder\sshd_config"

    $CurrentLogLevelConfig = ((gc "$TargetFolder\sshd_config") -imatch "^#*LogLevel\s\w*\b.*$")
    Write-Output 'Setting up SSH Logging'
    If ($SSHLogLevel)
    { #command line specified a log level - override whatever is there
      If ([bool]($CurrentLogLevelConfig -inotmatch "^LogLevel\s$SSHLogLevel\s*$"))
      {
        Write-Output "Current LogLevel setting in `"$TargetFolder\sshd_config`" is `"$CurrentLogLevelConfig`", setting it to `"LogLevel $SSHLogLevel`""
        (Get-Content "$TargetFolder\sshd_config") -replace "^#*LogLevel\s\w*\b.*$", "LogLevel $SSHLogLevel" | Set-Content "$TargetFolder\sshd_config"
      }
    }
    Else
    { #command line did not specify a log level, set it to QUIET - only if it has never been set (currently commented INFO setting)
      If((Test-Path "$TargetFolder\sshd_config") -AND ([bool]((gc "$TargetFolder\sshd_config") -ilike "#LogLevel INFO*")))
      {
        Write-Warning "Explicitly disabling sshd logging as it currently logs about .5 GB / hour"
        (Get-Content "$TargetFolder\sshd_config") -replace '#LogLevel INFO', 'LogLevel QUIET' | Set-Content "$TargetFolder\sshd_config"
      }
    }

     $CurrentPortConfig = ((gc "$TargetFolder\sshd_config") -match "^#*Port\s\d*\s*$")
     If ([bool]($CurrentPortConfig -notmatch "^Port $SSHServerPort"))
     {
       Write-Output "Current port setting in `"$TargetFolder\sshd_config`" is `"$CurrentPortConfig`", setting it to `"Port $SSHServerPort`""
       (Get-Content "$TargetFolder\sshd_config") -replace "^#*Port\s\d*\s*$", "Port $SSHServerPort" | Set-Content "$TargetFolder\sshd_config"
     }
     Else
     {
       Write-Output "Current port setting in `"$TargetFolder\sshd_config`" already matches `"Port $SSHServerPort`", no action necessary."
     }
  }

  If (!(Test-Path "$TargetFolder\KeysGenerated.flg"))
  { #Only ever generate a key the first time SSHD server is installed
      Write-Output "Generating sshd keys in `"$TargetFolder`""
      start-process "$TargetFolder\ssh-keygen.exe" -ArgumentList '-A' -WorkingDirectory "$TargetFolder" -nonewwindow -wait
      New-Item "$TargetFolder\KeysGenerated.flg" -type File | out-null
  }
  Else
  {
    Write-Warning "Found existing server ssh keys in $TargetFolder, you must delete them manually to generate new ones."
  }

  netsh advfirewall firewall add rule name='SSHD Port OpenSSH (chocolatey package: openssh)' dir=in action=allow protocol=TCP localport=$SSHServerPort

  If ($DeleteServerKeysAfterInstalled)
  {
    pushd $TargetFolder
    Foreach ($keyfile in $keylist)
    {
      If (Test-Path $keyfile)
      {
        Remove-Item $keyfile -force
      }
    }
    popd
  }
  Else
  {
    Write-Warning "The following private keys should be removed from the machine: $keylist"
  }
  New-Service -Name sshd -BinaryPathName "$TargetFolder\sshd.exe" -Description "SSH Daemon" -StartupType Automatic -DependsOn ssh-agent | Out-Null
  sc.exe config sshd obj= "NT SERVICE\SSHD"
  
  If (!$DisableKeyPermissionsReset)
  {
    Write-Host "Ensuring all ssh key and configuration files have correct permissions for all users"
    . "$TargetFolder\FixHostFilePermissions.ps1" -Confirm:$false
  }

  $logsdir = "$TargetFolder\Logs"
  If (!(Test-Path $logsdir))
  {
    New-Item $logsdir -ItemType Directory | out-null
    $rights = [System.Security.AccessControl.FileSystemRights]"Read, Write"
    $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("NT SERVICE\sshd", $rights, "ContainerInherit,ObjectInherit", "None", "Allow")
    If (!$RunningOnNano)
    {
      $aclAccess = (Get-Item -Path $logsdir).GetAccessControl('Access')
      $aclAccess.SetAccessRule($accessRule)
      Set-Acl -AclObject $aclAccess -Path $logsdir -Confirm:$false
    }
    Else
    {
      $aclAccess = Get-Acl -Path $logsdir
      $aclAccess.SetAccessRule($accessRule)
      Set-Acl -Path $logsdir -AclObject $aclAccess
    }
  }

  If (!$UseNTRights)
  {
    #The code in this .PS1 has been tested on Nano - the hardest case to date for setting special privileges in script
    . "$toolsdir\AddAccountToAssignPrimaryToken.ps1" -AccountToAdd "NT SERVICE\SSHD"
    . "$toolsdir\AddAccountToLogonAsAService.ps1" -AccountToAdd "NT SERVICE\SSHD"
  }
  Else
  {
    If (($OSBits -eq 64) -and (!(Test-Path "$env:windir\syswow64")))
    {
      Write-Warning "This 64-bit system does not have the WOW64 subsystem installed, please manually grant the right SeLogonAsAService to `"NT SERVICE\SSHD`"."
      Write-Warning "OR try again WITHOUT the /UseNTRights switch."
    }
    Else
    {
      write-output "Using ntrights.exe to grant logon as service."
      Start-Process "$TargetFolder\ntrights.exe" -ArgumentList "-u `"NT SERVICE\SSHD`" +r SeAssignPrimaryTokenPrivilege"
    }
  }
}

If (CheckServicePath 'sshd.exe' "$TargetFolder")
{
  write-output "Starting SSHD..."
  Start-Service SSHD
}
If (CheckServicePath 'ssh-agent.exe' "$TargetFolder")
{
  write-output "Starting SSH-Agent..."
  Start-Service SSH-Agent
}

$keylist = "ssh_host_dsa_key", "ssh_host_rsa_key", "ssh_host_ecdsa_key", "ssh_host_ed25519_key"
$fullpathkeylist = "'$TargetFolder\ssh_host_dsa_key'", "'$TargetFolder\ssh_host_rsa_key'", "'$TargetFolder\ssh_host_ecdsa_key'", "'$TargetFolder\ssh_host_ed25519_key'"


If ($SSHServerFeature)
{
  If (!(Test-Path "$TargetFolder\KeysAddedToAgent.flg"))
  {
    Write-Output "Installing Server Keys into SSH-Agent"

    schtasks.exe /create /RU "NT AUTHORITY\SYSTEM" /RL HIGHEST /SC ONSTART /TN "ssh-add" /TR "'$TargetFolder\ssh-add.exe'  $fullpathkeylist" /F

    schtasks.exe /Run /I /TN "ssh-add"

    schtasks.exe /Delete /TN "ssh-add" /F

    New-Item "$TargetFolder\KeysAddedToAgent.flg" -type File | out-null
  }
  
  If (!$SSHLSAFeaturesDisabled)
  {
  If ($SSHLsaNeedsUpdating -OR $SSHLsaNeedsInitialCopy)
  {
    Write-Warning "IMPORTANT: You must reboot so that key based authentication can be fully installed or upgraded for the SSHD Service."
  }
  If ($CopyLSAResult)
  {
    Write-Warning "CRITICAL: ssh-lsa.dll was updated - a reboot required to fully activate it."
  }
  }

}

If (Test-Path "$TargetFolder\ssh.exe") 
{
  Write-Output "`r`nNEW VERSIONS OF SSH EXES:"
  Write-Output "$(dir "$TargetFolder\*.exe" | select -expand fullname | get-command | select -expand fileversioninfo | ft filename, fileversion -auto | out-string)"
}

If (!$SSHLSAFeaturesDisabled)
{
If (Test-Path "$env:windir\system32\ssh-lsa.dll") 
{
  Write-Output "`r`nCURRENT VERSION OF SSH-LSA.DLL (ONLY REQUIRES UPDATE IF FILE SIZE CHANGES, MUST UNINSTALL, REBOOT, REINSTALL AND REBOOT TO UPGRADE):"
  Write-Output "`r`n  EXAMINE LOG ABOVE FOR MESSAGES AS TO WHETHER AN UPGRADE OF SSH-LSA.DLL IS ACTUALLY REQUIRED THIS TIME AROUND."
  Write-Output "$(get-command "$env:windir\system32\ssh-lsa.dll" | select -expand fileversioninfo | ft filename, fileversion -auto | out-string)"
}
}

If ($sshlsaisLocked)
{
  write-output ""
  Write-warning " YOU MUST REBOOT TO COMPLETELY REMOVE SSH-LSA.DLL FROM MEMORY AS IT IS NOT USED BY THIS VERSION OF OPENSSH"
}

write-output ""
Write-Warning "You must start a new prompt, or use the command 'refreshenv' (provided by your chocolatey install) to re-read the environment for the tools to be available in this shell session."
tools\chocolateyuninstall.ps1

$ErrorActionPreference = 'Stop'; # stop on all errors
$ProductName = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'ProductName').ProductName
$EditionId = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'EditionID').EditionId

Write-Output "Running on: $ProductName, ($EditionId)"

If ($EditionId -ilike '*Nano*')
{$RunningOnNano = $True}

If (Test-Path variable:shimgen)
{$RunningUnderChocolatey = $True}
Else
{  Write-Output "Running Without Chocolatey"}

$packageName= 'openssh'
$toolsDir   = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"

$OSBits = ([System.IntPtr]::Size * 8) #Get-ProcessorBits

#On 64-bit, always favor 64-bit Program Files no matter what our execution is now (works back past XP / Server 2003)
If ($env:ProgramFiles.contains('x86'))
{
  $PF = $env:ProgramFiles.replace(' (x86)','')
}
Else
{
  $PF = $env:ProgramFiles
}

#$TargetFolder = "$PF\OpenSSH"
$TargetFolder = "$PF\OpenSSH-Win$($OSBits)"
$TargetFolderOld = "$PF\OpenSSH-Win$($OSBits)"

If ($RunningUnderChocolatey)
{
  # Default the values before reading params
  $SSHServerFeature = $false
  $KeyBasedAuthenticationFeature = $false
  $DeleteConfigAndServerKeys = $false

  $arguments = @{};
  $packageParameters = $env:chocolateyPackageParameters
}
# Now parse the packageParameters using good old regular expression
if ($packageParameters) {
    $match_pattern = "\/(?<option>([a-zA-Z]+)):(?<value>([`"'])?([a-zA-Z0-9- _\\:\.]+)([`"'])?)|\/(?<option>([a-zA-Z]+))"
    #"
    $option_name = 'option'
    $value_name = 'value'

    if ($packageParameters -match $match_pattern ){
        $results = $packageParameters | Select-String $match_pattern -AllMatches
        $results.matches | % {
          $arguments.Add(
              $_.Groups[$option_name].Value.Trim(),
              $_.Groups[$value_name].Value.Trim())
      }
    }
    else
    {
      throw "Package Parameters were found but were invalid (REGEX Failure)"
    }

    if ($arguments.ContainsKey("SSHServerFeature")) {
        Write-Host "/SSHServerFeature - Uninstalling SSH Server Feature if Present."
        $SSHServerFeature = $true
    }

    if ($arguments.ContainsKey("DeleteConfigAndServerKeys")) {
        Write-Host "/DeleteConfigAndServerKeys - Removing SSH Config and Server Keys."
        $DeleteConfigAndServerKeys = $true
    }

} else {
    Write-Debug "No Package Parameters Passed in";
}

Function CheckServicePath ($ServiceEXE,$FolderToCheck)
{
  #The modern way:
  #Return ([bool]((Get-WmiObject win32_service | ?{$_.Name -ilike "*$ServiceEXE*"} | select -expand PathName) -ilike "*$FolderToCheck*"))
  #The NANO TP5 Compatible Way:
  Return ([bool]((wmic service | ?{$_ -ilike "*$ServiceEXE*"}) -ilike "*$FolderToCheck*"))
}

#$SSHServiceInstanceExistsAndIsOurs = ([bool]((Get-WmiObject win32_service | ?{$_.Name -ilike 'sshd'} | select -expand PathName) -ilike "*$TargetFolder*"))
$SSHServiceInstanceExistsAndIsOurs = CheckServicePath 'sshd' "$TargetFolder"
#$SSHAGENTServiceInstanceExistsAndIsOurs = ([bool]((Get-WmiObject win32_service | ?{$_.Name -ilike 'ssh-agent'} | select -expand PathName) -ilike "*$TargetFolder*"))
$SSHAGENTServiceInstanceExistsAndIsOurs = CheckServicePath 'ssh-agent' "$TargetFolder"

If ($SSHServerFeature -AND (!$SSHServiceInstanceExistsAndIsOurs) -AND (Get-Service sshd -ErrorAction SilentlyContinue))
{
  $ExistingSSHDInstancePath = (Get-WmiObject win32_service | ?{$_.Name -ilike 'sshd'} | select -expand PathName)
  Throw "You have requested that the SSHD service be uninstalled, but this system appears to have an instance of an SSHD service configured for another folder ($ExistingSSHDInstancePath).  Ignoring /SSHServerFeature"
  $SSHServerFeature = $False
}

If ((!$SSHServerFeature) -AND $SSHServiceInstanceExistsAndIsOurs)
{
  Throw "There is a configured instance of the SSHD service, please specify the /SSHServerFeature to confirm it is OK to UNINSTALL the SSHD service at this time."
}


If ([bool](get-process ssh -erroraction silentlycontinue | where {$_.Path -ilike "*$TargetPath*"}))
{
  Throw "It appears you have instances of ssh.exe (client) running from the folder this package installs to, please terminate them and try again."
}

If ($SSHServiceInstanceExistsAndIsOurs -AND ([bool](Get-Service SSHD -ErrorAction SilentlyContinue | where {$_.Status -ieq 'Running'})))
{
    Stop-Service SSHD -Force
    Stop-Service SSH-Agent -Force
    Start-Sleep -seconds 3
    If (([bool](Get-Service SSHD | where {$_.Status -ieq 'Running'})))
    {
      Throw "Could not stop the SSHD service, please stop manually and retry this package."
    }
    Stop-Service ssh-agent -Force
    Start-Sleep -seconds 3
    If (([bool](Get-Service ssh-agent | where {$_.Status -ieq 'Running'})))
    {
      Throw "Could not stop the ssh-agent service, please stop manually and retry this package."
    }
}

If ((get-item 'Registry::HKLM\System\CurrentControlSet\Control\Lsa').getvalue("authentication packages") -contains 'ssh-lsa')
{
  $KeyBasedAuthenticationFeatureINSTALLED = $True
  Write-Warning "ssh-lsa.dll will be deconfigured - but not deleted.  It must be manually deleted after a reboot."
}

#uninstall agent service if it was installed without SSHD
If ($SSHAGENTServiceInstanceExistsAndIsOurs -AND (!$SSHServiceInstanceExistsAndIsOurs))
{
  Stop-Service ssh-agent -Force
  sc.exe delete ssh-agent | out-null
}

If ($SSHServiceInstanceExistsAndIsOurs -AND ($SSHServerFeature))
{
  Stop-Service sshd -Force
  sc.exe delete sshd  | out-null
  Stop-Service ssh-agent -Force
  sc.exe delete ssh-agent | out-null
}

If ($KeyBasedAuthenticationFeatureINSTALLED)
{
  If (Test-Path "$env:windir\sysnative")
  { #We are running in a 32-bit process under 64-bit Windows
    $sys32dir = "$env:windir\sysnative"
  }
  Else
  { #We are on a 32-bit OS, or 64-bit proc on 64-bit OS
    $sys32dir = "$env:windir\system32"
  }

  $AuthpkgToRemove = 'ssh-lsa'
  foreach ($authpackage in (get-item 'Registry::HKLM\System\CurrentControlSet\Control\Lsa').getvalue("authentication packages"))
  {
    If ($authpackage)
    {
      If ($authpackage -ine "$AuthpkgToRemove")
      {
        [string[]]$Newauthpackages += "$authpackage"
      }
    }
  }
  Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\" "Authentication Packages" $Newauthpackages
}

#Don't remove config in case they reinstall.
If (($SSHServiceInstanceExistsAndIsOurs -AND $DeleteConfigAndServerKeys) -OR (!$SSHServiceInstanceExistsAndIsOurs))
{
    Write-Warning "Removing all config and server keys as requested by /DeleteConfigAndServerKeys"
    
    #Ensure we have permissions to all keys and config files:
    #$ErrorActionPreference = 'SilentlyContinue'
    Import-Module "$toolsdir\OpenSSHUtils"
    $RunningUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
    dir "$TargetFolder\*" | % {repair-filepermission -FilePath $_.fullname -Owners $RunningUser -ReadAccessOK $RunningUser -AnyAccessOK $RunningUser -confirm:$false}

    If (Test-Path $TargetFolder) {Remove-Item "$TargetFolder" -Recurse -Force}
    #$ErrorActionPreference = 'Stop'
}
Else
{

  If (Test-Path $TargetFolder) {Get-ChildItem "$TargetFolder\*.*" -include *.exe,*.dll,*.cmd,*.ps1,*.psm1,*.psd1 | Remove-Item -Recurse -Force}
  If (Test-Path "$TargetFolder\logs") {Remove-Item "$TargetFolder\logs" -Recurse -Force}
  Write-Warning "NOT REMOVED: Config files and any keys in `"$TargetFolder`" were NOT REMOVED - you must remove them manually or use the package uninstall parameter /DeleteConfigAndServerKeys."
}
netsh advfirewall firewall delete rule name='SSHD Port OpenSSH (chocolatey package: openssh)'

$PathToRemove = "$TargetFolder"
#Code has been modified to work with Nano - do not change method of environment variable access
#foreach ($path in [Environment]::GetEnvironmentVariable("PATH","Machine").split(';'))
foreach ($path in ((Get-ItemProperty 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment').path.split(';')))
{
  If ($Path)
  {
    If (($path -ine "$PathToRemove") -AND ($path -ine "$PathToRemove\"))
    {
      [string[]]$Newpath += "$path"
    }
  }
}
$AssembledNewPath = ($newpath -join(';')).trimend(';')

Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name 'PATH' -Value "$AssembledNewPath"

$TermVarExists = [bool](get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name 'TERM' -EA SilentlyContinue)
If ($TermVarExists)
{
  Remove-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name 'TERM'
}
tools\fileinuseutils.ps1


Add-Type @'
    using System;
    using System.Text;
    using System.Runtime.InteropServices;

    public class LockedFileUtils
    {
      public enum MoveFileFlags
      {
          MOVEFILE_REPLACE_EXISTING           = 0x00000001,
          MOVEFILE_COPY_ALLOWED               = 0x00000002,
          MOVEFILE_DELAY_UNTIL_REBOOT         = 0x00000004,
          MOVEFILE_WRITE_THROUGH              = 0x00000008,
          MOVEFILE_CREATE_HARDLINK            = 0x00000010,
          MOVEFILE_FAIL_IF_NOT_TRACKABLE      = 0x00000020
      }

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);

        public static bool DeleteLockedFile (string sourcefile)
        {
            return MoveFileEx(sourcefile, null, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
        }
        public static bool CopyLockedFile (string sourcefile, string destination)
        {
            return MoveFileEx(sourcefile, destination, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
        }
    }
'@

Function Remove-FileEvenIfLocked
{
  param ([parameter(mandatory=$true,ValueFromPipeline=$true)][string]$Path)
  Process
  {
    $path = (Resolve-Path $path -ErrorAction Stop).Path

    try
    {
      Remove-Item $path -ErrorAction Stop
    }
    catch [System.IO.IOException]
    {
      If ($_.exception -ilike "*used by another process*")
      {
        Write-host "$path is locked by another process, attempting to setup removal at reboot..."
        $deleteResult = [LockedFileUtils]::DeleteLockedFile($path)
        if ($deleteResult -eq $false)
        {
          throw "Was not able to remove in use file $path `r`n $(New-Object System.ComponentModel.Win32Exception)"
        }
        else
        {
          write-host "(File locked.  Deleting $path at next reboot.  Reboot is required to complete operation.)"
        }
      }
    }
  }
}

Function Copy-FileEvenIfLocked
{
  param ([parameter(mandatory=$true,ValueFromPipeline=$true)][string]$Path,
         [parameter(mandatory=$true,ValueFromPipeline=$true)][string]$Destination)
  Process
  {
    $Path = (Resolve-Path $path -ErrorAction Stop).Path
    Write-output "`$path is now $path"
    If (Test-Path $Destination)
    {
      $Destination = (Resolve-Path $Destination -ErrorAction Stop).Path
    }
    Write-output "`$Destination is now $Destination"

    try
    {
      Copy-Item $Path $Destination -ErrorAction Stop
      Return "RebootNotRequired"
    }
    catch [System.IO.IOException]
    {
      If ($_.exception -ilike "*used by another process*")
      {
        Write-host "$path is locked by another process, attempting to setup copy at reboot..."
        $copyResult = [LockedFileUtils]::CopyLockedFile($path,$Destination)
        if ($copyResult -eq $false)
        {
          throw "Was not able to copy in use file $path to $destination `r`n $(New-Object System.ComponentModel.Win32Exception)"
        }
        else
        {
          write-host "Destination file is locked.  Copying $path to $Destination at next reboot.  Reboot is required to complete operation.)"
          Return "RebootRequired"
        }
      }
    }
  }
}
tools\FixHostFilePermissions.ps1
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param ()
Set-StrictMode -Version 2.0
If (!(Test-Path variable:PSScriptRoot)) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition}
Import-Module $PSScriptRoot\OpenSSHUtils -Force

#check sshd config file
$sshdConfigPath = join-path $PSScriptRoot "sshd_config"
if(Test-Path $sshdConfigPath -PathType Leaf)
{
    Repair-SshdConfigPermission -FilePath $sshdConfigPath @psBoundParameters
}
else
{
    Write-host "$FilePath does not exist"  -ForegroundColor Yellow
}
 
#check host keys
<#
$warning = @"
To keep the host private keys secure, it is recommended to register them with ssh-agent following
steps in link https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH.
If you choose not to register the keys with ssh-agent, please grant sshd read access to the private host keys after run this script.
"@
$prompt = "Did you register host private keys with ssh-agent?"
$description = "Grant sshd read access to the private host keys"

if($pscmdlet.ShouldProcess($description, $prompt, $warning))
{
    $warning = @"
To keep the host private keys secure, it is recommended to register them with ssh-agent following
steps in link https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH.
If you choose not to register the keys with ssh-agent, please grant sshd read access to the private host keys after run this script.
"@
    Write-Warning $warning
    Write-Host " "
}#>

Get-ChildItem $PSScriptRoot\ssh_host_*_key -ErrorAction SilentlyContinue | % {    
    Repair-SshdHostKeyPermission -FilePath $_.FullName @psBoundParameters
}


#check authorized_keys
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"  -ErrorAction SilentlyContinue | % {
    $properties =  Get-ItemProperty $_.pspath  -ErrorAction SilentlyContinue
    $userProfilePath = ""
    if($properties)
    {
        $userProfilePath =  $properties.ProfileImagePath
    }
    $filePath = Join-Path $userProfilePath .ssh\authorized_keys
    if(Test-Path $filePath -PathType Leaf)
    {
        Repair-AuthorizedKeyPermission -FilePath $filePath @psBoundParameters
    }
}

Write-Host "   Done."
Write-Host " "
tools\FixUserFilePermissions.ps1
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param ()
Set-StrictMode -Version 2.0
If (!(Test-Path variable:PSScriptRoot)) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition}

Import-Module $PSScriptRoot\OpenSSHUtils -Force

if(Test-Path ~\.ssh\config -PathType Leaf)
{
    Repair-UserSshConfigPermission -FilePath ~\.ssh\config @psBoundParameters
}

Get-ChildItem ~\.ssh\* -Include "id_rsa","id_dsa" -ErrorAction SilentlyContinue | % {
    Repair-UserKeyPermission -FilePath $_.FullName @psBoundParameters
}

Write-Host "   Done."
Write-Host " "
tools\Get-NetStat.ps1
function Get-NetStat
{
<#
.SYNOPSIS
	This function will get the output of netstat -n and parse the output
.DESCRIPTION
	This function will get the output of netstat -n and parse the output
.LINK
	http://www.lazywinadmin.com/2014/08/powershell-parse-this-netstatexe.html
.NOTES
	Francois-Xavier Cat
	www.lazywinadmin.com
	@LazyWinAdm

  2016/09/20 - Modified by DawinJS to:
  - only grab TCP ports so that parsing PID would be reliable (and is sufficient for my purposes)
  - If -GetProcessDetails
    - parse PID
    - use "get-process" to find exe name (netstat -b is not pulling it for my scenario)
    - finds a full process path name in a Nano TP5 compatible way (WMIC)
  - If -ShowProgress - show progress bar - takes a while to grab all exe paths for all processes
  - If -FilterOnPorts - filter results for these ports before grabbing process details

#>
Param (
  [switch]$ShowProgress,
  [string[]]$FilterOnPorts,
  [switch]$GetProcessDetails
  )
	PROCESS
	{
		# Get the output of netstat
		$data = netstat -a -n -o -p TCP | select -skip 4

		# Keep only the line with the data (we remove the first lines)
		#$data = $data[4..$data.count]

		# Each line need to be splitted and get rid of unnecessary spaces
		foreach ($line in $data)
		{
      If ($ShowProgress)
      {
        $ItemBeingProcessed++
        $percentdone = [math]::round(($ItemBeingProcessed/$data.count) * 100)
        Write-Progress -Activity "Probing Listening Ports" -Status "$percentdone% Complete:" -PercentComplete $percentdone
      }

      $AddInstance = $True
      # Get rid of the first whitespaces, at the beginning of the line
			$line = $line -replace '^\s+', ''

			# Split each property on whitespaces block
			$line = $line -split '\s+'

      $PortFromNetStat = (($line[1] -split ":")[1]).trim(' ')

      If ($FilterOnPorts)
      {
         If  (!($FilterOnPorts -contains $PortFromNetStat))
         {
           $AddInstance = $False
         }
      }

      If ($GetProcessDetails -AND $AddInstance)
      {
        If ($line[4].length -ge 1)
        {
        $ProcessInfo = Get-Process -id $($line[4])
        $ProcessEXEPath = $null

        If ([string](wmic process where "ProcessId='$($line[4])'" get ExecutablePath /format:list) -match "[A-Z]:\\.*exe")
        {
          #write-output "match: *$($Matches[0])*"
          $ProcessEXEPath = "$($Matches[0])"
        }
   <#
           If (Test-Path variable:matches) {write-host "got a match"}

            If ($getresult.GetType().Name -eq 'Boolean')
            {
              $ProcessEXEPath = ($Matches[0]).trimend(' ')
            }
            ElseIf ($getresult.GetType().Name -eq 'String')
            {
              $ProcessEXEPath = $getresult.trimend(' ')
            }
            Else
            {
              $ProcessEXEPath = ''
            }
            #>
        }
      }
      If ($AddInstance)
      {
			# Define the properties
  			$properties = @{
	  			Protocol = $line[0].trim(' ')
		  		LocalAddressIP = ($line[1] -split ":")[0].trim(' ')
			  	LocalAddressPort = $PortFromNetStat
          LocalAddressPID = ($line[4]).trim(' ')
          LocalAddressProcessName = $ProcessInfo.Name
          LocalAddressProcessPath = $ProcessEXEPath
		  		ForeignAddressIP = ($line[2] -split ":")[0].trim(' ')
			  	ForeignAddressPort = ($line[2] -split ":")[1].trim(' ')
				  State = $line[3]
			  }

			  # Output the current line
			  New-Object -TypeName PSObject -Property $properties
      }
		}
	}
}
tools\LICENSE.txt
This file is part of the OpenSSH software.

The licences which components of this software fall under are as
follows.  First, we will summarize and say that all components
are under a BSD licence, or a licence more free than that.

OpenSSH contains no GPL code.

1)
     * Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
     *                    All rights reserved
     *
     * As far as I am concerned, the code I have written for this software
     * can be used freely for any purpose.  Any derived versions of this
     * software must be clearly marked as such, and if the derived work is
     * incompatible with the protocol description in the RFC file, it must be
     * called by a name other than "ssh" or "Secure Shell".

    [Tatu continues]
     *  However, I am not implying to give any licenses to any patents or
     * copyrights held by third parties, and the software includes parts that
     * are not under my direct control.  As far as I know, all included
     * source code is used in accordance with the relevant license agreements
     * and can be used freely for any purpose (the GNU license being the most
     * restrictive); see below for details.

    [However, none of that term is relevant at this point in time.  All of
    these restrictively licenced software components which he talks about
    have been removed from OpenSSH, i.e.,

     - RSA is no longer included, found in the OpenSSL library
     - IDEA is no longer included, its use is deprecated
     - DES is now external, in the OpenSSL library
     - GMP is no longer used, and instead we call BN code from OpenSSL
     - Zlib is now external, in a library
     - The make-ssh-known-hosts script is no longer included
     - TSS has been removed
     - MD5 is now external, in the OpenSSL library
     - RC4 support has been replaced with ARC4 support from OpenSSL
     - Blowfish is now external, in the OpenSSL library

    [The licence continues]

    Note that any information and cryptographic algorithms used in this
    software are publicly available on the Internet and at any major
    bookstore, scientific library, and patent office worldwide.  More
    information can be found e.g. at "http://www.cs.hut.fi/crypto".

    The legal status of this program is some combination of all these
    permissions and restrictions.  Use only at your own responsibility.
    You will be responsible for any legal consequences yourself; I am not
    making any claims whether possessing or using this is legal or not in
    your country, and I am not taking any responsibility on your behalf.


			    NO WARRANTY

    BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
    REPAIR OR CORRECTION.

    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
    OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
    TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
    YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
    PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGES.

2)
    The 32-bit CRC compensation attack detector in deattack.c was
    contributed by CORE SDI S.A. under a BSD-style license.

     * Cryptographic attack detector for ssh - source code
     *
     * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
     *
     * All rights reserved. Redistribution and use in source and binary
     * forms, with or without modification, are permitted provided that
     * this copyright notice is retained.
     *
     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
     * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
     * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
     * SOFTWARE.
     *
     * Ariel Futoransky <[email protected]>
     * <http://www.core-sdi.com>

3)
    ssh-keyscan was contributed by David Mazieres under a BSD-style
    license.

     * Copyright 1995, 1996 by David Mazieres <[email protected]>.
     *
     * Modification and redistribution in source and binary forms is
     * permitted provided that due credit is given to the author and the
     * OpenBSD project by leaving this copyright notice intact.

4)
    The Rijndael implementation by Vincent Rijmen, Antoon Bosselaers
    and Paulo Barreto is in the public domain and distributed
    with the following license:

     * @version 3.0 (December 2000)
     *
     * Optimised ANSI C code for the Rijndael cipher (now AES)
     *
     * @author Vincent Rijmen <[email protected]>
     * @author Antoon Bosselaers <[email protected]>
     * @author Paulo Barreto <[email protected]>
     *
     * This code is hereby placed in the public domain.
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

5)
    One component of the ssh source code is under a 3-clause BSD license,
    held by the University of California, since we pulled these parts from
    original Berkeley code.

     * Copyright (c) 1983, 1990, 1992, 1993, 1995
     *      The Regents of the University of California.  All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     * 3. Neither the name of the University nor the names of its contributors
     *    may be used to endorse or promote products derived from this software
     *    without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     * SUCH DAMAGE.

6)
    Remaining components of the software are provided under a standard
    2-term BSD licence with the following names as copyright holders:

	Markus Friedl
	Theo de Raadt
	Niels Provos
	Dug Song
	Aaron Campbell
	Damien Miller
	Kevin Steves
	Daniel Kouril
	Wesley Griffin
	Per Allansson
	Nils Nordman
	Simon Wilkinson

    Portable OpenSSH additionally includes code from the following copyright
    holders, also under the 2-term BSD license:

	Ben Lindstrom
	Tim Rice
	Andre Lucas
	Chris Adams
	Corinna Vinschen
	Cray Inc.
	Denis Parker
	Gert Doering
	Jakob Schlyter
	Jason Downs
	Juha Yrj�l�
	Michael Stone
	Networks Associates Technology, Inc.
	Solar Designer
	Todd C. Miller
	Wayne Schroeder
	William Jones
	Darren Tucker
	Sun Microsystems
	The SCO Group
	Daniel Walsh
	Red Hat, Inc
	Simon Vallet / Genoscope

     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

8) Portable OpenSSH contains the following additional licenses:

    a) md5crypt.c, md5crypt.h

	 * "THE BEER-WARE LICENSE" (Revision 42):
	 * <[email protected]> wrote this file.  As long as you retain this
	 * notice you can do whatever you want with this stuff. If we meet
	 * some day, and you think this stuff is worth it, you can buy me a
	 * beer in return.   Poul-Henning Kamp

    b) snprintf replacement

	* Copyright Patrick Powell 1995
	* This code is based on code written by Patrick Powell
	* ([email protected]) It may be used for any purpose as long as this
	* notice remains intact on all source code distributions

    c) Compatibility code (openbsd-compat)

       Apart from the previously mentioned licenses, various pieces of code
       in the openbsd-compat/ subdirectory are licensed as follows:

       Some code is licensed under a 3-term BSD license, to the following
       copyright holders:

	Todd C. Miller
	Theo de Raadt
	Damien Miller
	Eric P. Allman
	The Regents of the University of California
	Constantin S. Svintsoff

	* Redistribution and use in source and binary forms, with or without
	* modification, are permitted provided that the following conditions
	* are met:
	* 1. Redistributions of source code must retain the above copyright
	*    notice, this list of conditions and the following disclaimer.
	* 2. Redistributions in binary form must reproduce the above copyright
	*    notice, this list of conditions and the following disclaimer in the
	*    documentation and/or other materials provided with the distribution.
	* 3. Neither the name of the University nor the names of its contributors
	*    may be used to endorse or promote products derived from this software
	*    without specific prior written permission.
	*
	* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
	* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
	* ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
	* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
	* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
	* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
	* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
	* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
	* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
	* SUCH DAMAGE.

       Some code is licensed under an ISC-style license, to the following
       copyright holders:

	Internet Software Consortium.
	Todd C. Miller
	Reyk Floeter
	Chad Mynhier

	* Permission to use, copy, modify, and distribute this software for any
	* purpose with or without fee is hereby granted, provided that the above
	* copyright notice and this permission notice appear in all copies.
	*
	* THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
	* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
	* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
	* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
	* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
	* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
	* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

       Some code is licensed under a MIT-style license to the following
       copyright holders:

	Free Software Foundation, Inc.

	* Permission is hereby granted, free of charge, to any person obtaining a  *
	* copy of this software and associated documentation files (the            *
	* "Software"), to deal in the Software without restriction, including      *
	* without limitation the rights to use, copy, modify, merge, publish,      *
	* distribute, distribute with modifications, sublicense, and/or sell       *
	* copies of the Software, and to permit persons to whom the Software is    *
	* furnished to do so, subject to the following conditions:                 *
	*                                                                          *
	* The above copyright notice and this permission notice shall be included  *
	* in all copies or substantial portions of the Software.                   *
	*                                                                          *
	* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
	* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
	* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
	* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
	* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
	* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
	* THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
	*                                                                          *
	* Except as contained in this notice, the name(s) of the above copyright   *
	* holders shall not be used in advertising or otherwise to promote the     *
	* sale, use or other dealings in this Software without prior written       *
	* authorization.                                                           *
	****************************************************************************/


------
$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $
tools\ntrights.exe
md5: 416C43AEB17252EE33048BD1F277D2A5 | sha1: 085DEB77551F9F6201E5AA352B62CAD91C3005E5 | sha256: F46BAA1B6227226518E42263E9B4808F81C27D060207DF160F9AC64DEAE4F4F5 | sha512: 3155DE3FB04F1DF246D6CECFA1C89F8AE9963C18BE1CE717731FF210AB39D537BE01231002A54D4346B4116E3505F387C92DFECC18A80CE7EB99C6D33E5F1F2A
tools\ntrights.exe.ignore
 
tools\OpenSSH-Win32.zip
md5: 4337C572D4DC6E875FF2639A8D00473E | sha1: E39CB40DAA37B493F42A77DDC7B57A4E7674997E | sha256: A467C502688FDE09F619567A00630E2436D43D9797D2DEB759E8FFD10F6C22EB | sha512: 78B2BFB78C40AF1CAAD485D47E1837D043C9416D570A0D679E71E9BD95120C195F27F2F47FDB8EDB7EDCB6F1C03A0E9154919A091F69BD34E688CA5B4C3FD318
tools\OpenSSH-Win64.zip
md5: B5A2C14F3035C1B359D7D5727AC6F203 | sha1: B797E0DB1D4D2702F6BEE49FD178E6E94596C290 | sha256: 7680788B3CDB2338ABCDC05A0F8D37B19F7D3B763C0EAB289242A8D0FC0BB325 | sha512: 935D7A3BF6D0152C19733A829057C018A0D10B2C87946D666E733075CF5E85737F4545F9784D6599CCC7826B3B3D3AB640BC18FD24E6686343150E2013B52DB0
tools\OpenSSHUtils.psd1
#
# Module manifest for module 'OpenSSHUtils'
#
# Generated on: 6/9/2017
#

@{

# Script module or binary module file associated with this manifest
ModuleToProcess = 'OpenSSHUtils.psm1'

# Version number of this module.
ModuleVersion = '1.0.0.1'

# ID used to uniquely identify this module
GUID = '08285dee-3d08-476b-8948-1a7e2562c079'

# Author of this module
Author = 'Yanbing Wang'

# Company or vendor of this module
CompanyName = ''

# Copyright statement for this module
Copyright = ''

# Description of the functionality provided by this module
Description = 'Configure OpenSSH for Windows related security settings like file owner and permissions.'

# Functions to export from this module
FunctionsToExport = '*'

# Cmdlets to export from this module
CmdletsToExport = '*'

# Variables to export from this module
VariablesToExport = '*'

# Aliases to export from this module
AliasesToExport = '*'

# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '2.0'
}
tools\OpenSSHUtils.psm1
Set-StrictMode -Version 2.0
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")            
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
$everyone =  New-Object System.Security.Principal.NTAccount("EveryOne")
$sshdAccount = New-Object System.Security.Principal.NTAccount("NT SERVICE","sshd")

<#
    .Synopsis
    Repair-SshdConfigPermission
    Repair the file owner and Permission of sshd_config
#>
function Repair-SshdConfigPermission
{
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param (
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]        
        [string]$FilePath)

        Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessNeeded $sshdAccount @psBoundParameters        
}

<#
    .Synopsis
    Repair-SshdHostKeyPermission
    Repair the file owner and Permission of host private and public key
    -FilePath: The path of the private host key
#>
function Repair-SshdHostKeyPermission
{
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param (
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]        
        [string]$FilePath)        
        
        if($PSBoundParameters["FilePath"].EndsWith(".pub"))
        {
            $PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
        }

        Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessNeeded $sshdAccount @psBoundParameters        
        
        $PSBoundParameters["FilePath"] += ".pub"        
        Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessOK $everyone -ReadAccessNeeded $sshdAccount @psBoundParameters        
}

<#
    .Synopsis
    Repair-AuthorizedKeyPermission
    Repair the file owner and Permission of authorized_keys
#>
function Repair-AuthorizedKeyPermission
{
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param (
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]        
        [string]$FilePath)        

        if(-not (Test-Path $FilePath -PathType Leaf))
        {
            Write-host "$FilePath not found" -ForegroundColor Yellow
            return
        }
        $fullPath = (Resolve-Path $FilePath).Path
        $profileListPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
        $profileItem = Get-ChildItem $profileListPath  -ErrorAction SilentlyContinue | ? {
            $properties =  Get-ItemProperty $_.pspath  -ErrorAction SilentlyContinue
            $userProfilePath = $null
            if($properties)
            {
                $userProfilePath =  $properties.ProfileImagePath
            }
            $fullPath -ieq "$userProfilePath\.ssh\authorized_keys"
        }
        if($profileItem)
        {
            $userSid = $profileItem.PSChildName
            $account = Get-UserAccount -UserSid $userSid
            if($account)
            {
                Repair-FilePermission -Owners $account,$adminsAccount,$systemAccount -AnyAccessOK $account -ReadAccessNeeded $sshdAccount @psBoundParameters
            }
            else
            {
                Write-host "Can't translate $userSid to an account. skip checking $fullPath..." -ForegroundColor Yellow
            }
        }
        else
        {
            Write-host "$fullPath is not in the profile folder of any user. Skip checking..." -ForegroundColor Yellow
        }
}

<#
    .Synopsis
    Repair-UserKeyPermission
    Repair the file owner and Permission of user config
    -FilePath: The path of the private user key
    -User: The user associated with this ssh config
#>
function Repair-UserKeyPermission
{
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param (
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]        
        [string]$FilePath,
        [System.Security.Principal.NTAccount] $User = $currentUser)

        if($PSBoundParameters["FilePath"].EndsWith(".pub"))
        {
            $PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
        }
        Repair-FilePermission -Owners $User, $adminsAccount,$systemAccount -AnyAccessOK $User @psBoundParameters
        
        $PSBoundParameters["FilePath"] += ".pub"
        Repair-FilePermission -Owners $User, $adminsAccount,$systemAccount -AnyAccessOK $User -ReadAccessOK $everyone @psBoundParameters
}

<#
    .Synopsis
    Repair-UserSSHConfigPermission
    Repair the file owner and Permission of user config
#>
function Repair-UserSshConfigPermission
{
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param (
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]        
        [string]$FilePath)
        Repair-FilePermission -Owners $currentUser,$adminsAccount,$systemAccount -AnyAccessOK $currentUser @psBoundParameters
}

<#
    .Synopsis
    Repair-FilePermissionInternal
    Only validate owner and ACEs of the file
#>
function Repair-FilePermission
{
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param (        
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]        
        [string]$FilePath,
        [ValidateNotNull()]
        [System.Security.Principal.NTAccount[]] $Owners = $currentUser,
        [System.Security.Principal.NTAccount[]] $AnyAccessOK,
        [System.Security.Principal.NTAccount[]] $ReadAccessOK,
        [System.Security.Principal.NTAccount[]] $ReadAccessNeeded
    )

    if(-not (Test-Path $FilePath -PathType Leaf))
    {
        Write-host "$FilePath not found" -ForegroundColor Yellow
        return
    }
    
    Write-host "  [*] $FilePath"
    $return = Repair-FilePermissionInternal @PSBoundParameters

    if($return -contains $true) 
    {
        #Write-host "Re-check the health of file $FilePath"
        Repair-FilePermissionInternal @PSBoundParameters
    }
}

<#
    .Synopsis
    Repair-FilePermissionInternal
#>
function Repair-FilePermissionInternal {
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param (
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$FilePath,
        [ValidateNotNull()]
        [System.Security.Principal.NTAccount[]] $Owners = $currentUser,
        [System.Security.Principal.NTAccount[]] $AnyAccessOK,
        [System.Security.Principal.NTAccount[]] $ReadAccessOK,
        [System.Security.Principal.NTAccount[]] $ReadAccessNeeded
    )

    $acl = Get-Acl $FilePath
    $needChange = $false
    $health = $true
    $paras = @{}
    $PSBoundParameters.GetEnumerator() | % { if((-not $_.key.Contains("Owners")) -and (-not $_.key.Contains("Access"))) { $paras.Add($_.key,$_.Value) } }
    
    $validOwner = $owners | ? { $_.equals([System.Security.Principal.NTAccount]$acl.owner)}
    if($validOwner -eq $null)
    {        
        $caption = "Current owner: '$($acl.Owner)'. '$($Owners[0])' should own '$FilePath'."
        $prompt = "Shall I set the file owner?"
        $description = "Set '$($Owners[0])' as owner of '$FilePath'."        
        if($pscmdlet.ShouldProcess($description, $prompt, $caption))
	    {   
            Enable-Privilege SeRestorePrivilege | out-null
            $acl.SetOwner($Owners[0])
            Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
            if($e)
            {
                Write-Warning "Set owner failed with error: $($e[0].ToString())."
            }
            else
            {
                Write-Host "'$($Owners[0])' now owns '$FilePath'. " -ForegroundColor Green
            }
        }
        else
        {
            $health = $false
            if(-not $PSBoundParameters.ContainsKey("WhatIf"))
            {
                Write-Host "The owner is still set to '$($acl.Owner)'." -ForegroundColor Yellow
            }
        }
    }

    $ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
                    ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)

    #system and admin groups can have any access to the file; plus the account in the AnyAccessOK list
    $realAnyAccessOKList = $AnyAccessOK + @($systemAccount, $adminsAccount)

    #if accounts in the ReadAccessNeeded already part of dacl, they are okay; need to make sure they have read access only
    $realReadAcessOKList = $ReadAccessOK + $ReadAccessNeeded

    #this is orginal list requested by the user, the account will be removed from the list if they already part of the dacl
    $realReadAccessNeeded = $ReadAccessNeeded

    #'APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES'- can't translate fully qualified name. it is a win32 API bug.
    #'ALL APPLICATION PACKAGES' exists only on Win2k12 and Win2k16 and 'ALL RESTRICTED APPLICATION PACKAGES' exists only in Win2k16
    $specialIdRefs = "ALL APPLICATION PACKAGES","ALL RESTRICTED APPLICATION PACKAGES"

    foreach($a in $acl.Access)
    {
        if($realAnyAccessOKList -and (($realAnyAccessOKList | ? { $_.equals($a.IdentityReference)}) -ne $null))
        {
            #ignore those accounts listed in the AnyAccessOK list.
        }
        #If everyone is in the ReadAccessOK list, any user can have read access;
        # below block make sure they are granted Read access only
        elseif($realReadAcessOKList -and (($realReadAcessOKList | ? { $_.Equals($everyone)}) -ne $null) -or `
             (($realReadAcessOKList | ? { $_.equals($a.IdentityReference)}) -ne $null))
        {
            if($realReadAccessNeeded -and ($a.IdentityReference.Equals($everyone)))
            {
                $realReadAccessNeeded=@()
            }
            elseif($realReadAccessNeeded)
            {
                $realReadAccessNeeded = $realReadAccessNeeded | ? { -not $_.Equals($a.IdentityReference) }
            }

            if (-not ($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -or `
            (-not (([System.UInt32]$a.FileSystemRights.value__) -band (-bnot $ReadAccessPerm))))
            {
                continue;
            }           
            
            if($a.IsInherited)
            {
                if($needChange)    
                {
                    Enable-Privilege SeRestorePrivilege | out-null
                    Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
                    if($e)
                    {
                        Write-Warning "Repair permission failed with error: $($e[0].ToString())."
                    }
                }
                
                return Remove-RuleProtection @paras
            }
            $caption = "'$($a.IdentityReference)' has the following access to '$FilePath': '$($a.FileSystemRights)'."
            $prompt = "Shall I make it Read only?"
            $description = "Set'$($a.IdentityReference)' Read access only to '$FilePath'. "

            if($pscmdlet.ShouldProcess($description, $prompt, $caption))
	        {
                $needChange = $true
                $idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
                if ($specialIdRefs -icontains $idRefShortValue )
                {
                    $ruleIdentity = Get-UserSID -User (New-Object Security.Principal.NTAccount $idRefShortValue)
                    if($ruleIdentity)
                    {
                        $ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
                            ($ruleIdentity, "Read", "None", "None", "Allow")
                    }
                    else
                    {
                        Write-Warning "Can't translate '$idRefShortValue'. "
                        continue
                    }                    
                }
                else
                {
                    $ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
                        ($a.IdentityReference, "Read", "None", "None", "Allow")
                    }
                $acl.SetAccessRule($ace)
                Write-Host "'$($a.IdentityReference)' now has Read access to '$FilePath'. "  -ForegroundColor Green
            }
            else
            {
                $health = $false
                if(-not $PSBoundParameters.ContainsKey("WhatIf"))
                {
                    Write-Host "'$($a.IdentityReference)' still has these access to '$FilePath': '$($a.FileSystemRights)'." -ForegroundColor Yellow
                }
            }
        }
        #other than AnyAccessOK and ReadAccessOK list, if any other account is allowed, they should be removed from the dacl
        elseif($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow))
        {            
            $caption = "'$($a.IdentityReference)' should not have access to '$FilePath'." 
            if($a.IsInherited)
            {
                if($needChange)    
                {
                    Enable-Privilege SeRestorePrivilege | out-null
                    Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
                    if($e)
                    {
                        Write-Warning "Repair permission failed with error: $($e[0].ToString())."
                    }
                }
                return Remove-RuleProtection @paras
            }
            
            $prompt = "Shall I remove this access?"
            $description = "Remove access rule of '$($a.IdentityReference)' from '$FilePath'."

            if($pscmdlet.ShouldProcess($description, $prompt, "$caption."))
	        {  
                $needChange = $true
                $ace = $a
                $idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
                if ($specialIdRefs -icontains $idRefShortValue)
                {                    
                    $ruleIdentity = Get-UserSID -User (New-Object Security.Principal.NTAccount $idRefShortValue)
                    if($ruleIdentity)
                    {
                        $ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
                            ($ruleIdentity, $a.FileSystemRights, $a.InheritanceFlags, $a.PropagationFlags, $a.AccessControlType)
                    }
                    else
                    {
                        Write-Warning "Can't translate '$idRefShortValue'. "
                        continue
                    }
                }

                if(-not ($acl.RemoveAccessRule($ace)))
                {
                    Write-Warning "Failed to remove access of '$($a.IdentityReference)' from '$FilePath'."
                }
                else
                {
                    Write-Host "'$($a.IdentityReference)' has no more access to '$FilePath'." -ForegroundColor Green
                }
            }
            else
            {
                $health = $false
                if(-not $PSBoundParameters.ContainsKey("WhatIf"))
                {
                    Write-Host "'$($a.IdentityReference)' still has access to '$FilePath'." -ForegroundColor Yellow                
                }        
            }
        }
    }

    #This is the real account list we need to add read access to the file
    if($realReadAccessNeeded)
    {
        $realReadAccessNeeded | % {
            if((Get-UserSID -User $_) -eq $null)
            {
                Write-Warning "'$_' needs Read access to '$FilePath', but it can't be translated on the machine."
            }
            else
            {
                $caption = "'$_' needs Read access to '$FilePath'."
                $prompt = "Shall I make the above change?"
                $description = "Set '$_' Read only access to '$FilePath'. "

                if($pscmdlet.ShouldProcess($description, $prompt, $caption))
	            {
                    $needChange = $true
                    $ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
                            ($_, "Read", "None", "None", "Allow")
                    $acl.AddAccessRule($ace)
                    Write-Host "'$_' now has Read access to '$FilePath'." -ForegroundColor Green
                }
                else
                {
                    $health = $false
                    if(-not $PSBoundParameters.ContainsKey("WhatIf"))
                    {
                        Write-Host "'$_' does not have Read access to '$FilePath'." -ForegroundColor Yellow
                    }
                }
            }
        }
    }

    if($needChange)    
    {
        Enable-Privilege SeRestorePrivilege | out-null
        Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
        if($e)
        {
            Write-Warning "Repair permission failed with error: $($e[0].ToString())."
        }
    }
    if($health)
    {
        if ($needChange) 
        {
            Write-Host "      Repaired permissions" -ForegroundColor Yellow
        }
        else
        {
            Write-Host "      looks good"  -ForegroundColor Green
        }
    }
    Write-host " "
}

<#
    .Synopsis
    Remove-RuleProtection
#>
function Remove-RuleProtection
{
    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param (
        [parameter(Mandatory=$true)]
        [string]$FilePath
    )
    $message = "Need to remove the inheritance before repair the rules."
    $prompt = "Shall I remove the inheritace?"
    $description = "Remove inheritance of '$FilePath'."

    if($pscmdlet.ShouldProcess($description, $prompt, $message))
	{
        $acl = Get-acl -Path $FilePath
        $acl.SetAccessRuleProtection($True, $True)
        Enable-Privilege SeRestorePrivilege | out-null
        Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
        if($e)
        {
            Write-Warning "Remove-RuleProtection failed with error: $($e[0].ToString())."
        }
              
        Write-Host "Inheritance is removed from '$FilePath'."  -ForegroundColor Green
        return $true
    }
    elseif(-not $PSBoundParameters.ContainsKey("WhatIf"))
    {        
        Write-Host "inheritance is not removed from '$FilePath'. Skip Checking FilePath."  -ForegroundColor Yellow
        return $false
    }
}
<#
    .Synopsis
    Get-UserAccount
#>
function Get-UserAccount
{
    param
        (   [parameter(Mandatory=$true)]      
            [string]$UserSid
        )
    try
    {
        $objSID = New-Object System.Security.Principal.SecurityIdentifier($UserSid) 
        $objUser = $objSID.Translate( [System.Security.Principal.NTAccount]) 
        $objUser
    }
    catch {
    }
}

<#
    .Synopsis
    Get-UserSID
#>
function Get-UserSID
{
    param ([System.Security.Principal.NTAccount]$User)    
    try
    {
        $User.Translate([System.Security.Principal.SecurityIdentifier])
    }
    catch {
    }
}

function Enable-Privilege {
 param(
  ## The privilege to adjust. This set is taken from
  ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
  [ValidateSet(
   "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
   "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
   "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
   "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
   "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege",
   "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege",
   "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege",
   "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
   "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege",
   "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege",
   "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
  $Privilege,
  ## Switch to disable the privilege, rather than enable it.
  [Switch] $Disable
 )

 ## Taken from P/Invoke.NET with minor adjustments.
 $definition = @'
 using System;
 using System.Runtime.InteropServices;
  
 public class AdjPriv
 {
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
   ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
  [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern IntPtr GetCurrentProcess();
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
  [DllImport("advapi32.dll", SetLastError = true)]
  internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  internal struct TokPriv1Luid
  {
   public int Count;
   public long Luid;
   public int Attr;
  }
  
  internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
  internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
  internal const int TOKEN_QUERY = 0x00000008;
  internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
  public static bool EnablePrivilege(string privilege, bool disable)
  {
   bool retVal;
   TokPriv1Luid tp;
   IntPtr hproc = GetCurrentProcess();
   IntPtr htok = IntPtr.Zero;
   retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
   tp.Count = 1;
   tp.Luid = 0;
   if(disable)
   {
    tp.Attr = SE_PRIVILEGE_DISABLED;
   }
   else
   {
    tp.Attr = SE_PRIVILEGE_ENABLED;
   }
   retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
   retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
   return retVal;
  }
 }
'@

 
 $type = Add-Type $definition -PassThru
 $type[0]::EnablePrivilege($Privilege, $Disable)
}

Export-ModuleMember -Function Repair-FilePermission, Repair-SshdConfigPermission, Repair-SshdHostKeyPermission, Repair-AuthorizedKeyPermission, Repair-UserKeyPermission, Repair-UserSshConfigPermission
tools\VERIFICATION.txt
VERIFICATION.txt is intended to assist the Chocolatey moderators and community
in verifying that this package's contents are trustworthy.

To verify:

1. Download https://github.com/PowerShell/Win32-OpenSSH/releases/download/5_30_2016/OpenSSH-Win64.zip
2. Compare OpenSSH-Win64.zip hash with bundled OpenSSH-Win64.zip hash.
3. Download https://github.com/PowerShell/Win32-OpenSSH/releases/download/5_30_2016/OpenSSH-Win32.zip
4. Compare OpenSSH-Win64.zip hash with bundled OpenSSH-Win32.zip hash.

Log in or click on link to see number of positives.

In cases where actual malware is found, the packages are subject to removal. Software sometimes has false positives. Moderators do not necessarily validate the safety of the underlying software, only that a package retrieves software from the official distribution point and/or validate embedded software against official distribution point (where distribution rights allow redistribution).

Chocolatey Pro provides runtime protection from possible malware.

Add to Builder Version Downloads Last Updated Status
Win32 OpenSSH (Universal Installer) 9.5.0-beta20240403 17676 Wednesday, April 3, 2024 Exempted
Win32 OpenSSH (Universal Installer) 9.5.0-beta1 9785 Saturday, December 30, 2023 Exempted
Win32 OpenSSH (Universal Installer) 9.4.0-beta1 99 Saturday, December 30, 2023 Exempted
Win32 OpenSSH (Universal Installer) 9.2.2-beta1 12075 Thursday, May 18, 2023 Exempted
Win32 OpenSSH (Universal Installer) 9.2.0-beta1 52 Saturday, December 30, 2023 Exempted
Win32 OpenSSH (Universal Installer) 9.1.0-beta1 37 Saturday, December 30, 2023 Exempted
Win32 OpenSSH (Universal Installer) 8.9.1-beta1 79 Saturday, December 30, 2023 Exempted
Win32 OpenSSH (Universal Installer) 8.9.0-beta1 53 Friday, December 29, 2023 Exempted
Win32 OpenSSH (Universal Installer) 8.6.0-beta1 78158 Saturday, May 29, 2021 Approved
Win32 OpenSSH (Universal Installer) 8.1.0-beta 56020 Tuesday, January 14, 2020 Approved
Win32 OpenSSH (Universal Installer) 7.9.0.1 599779 Sunday, January 13, 2019 Approved
Win32 OpenSSH (Universal Installer) 7.7.2.1 1881732 Sunday, July 29, 2018 Approved
Win32 OpenSSH (Universal Installer) 7.7.1.1 260380 Tuesday, June 5, 2018 Approved
Win32 OpenSSH (Universal Installer) 7.7.0.1 17880 Friday, June 1, 2018 Approved
Win32 OpenSSH (Universal Installer) 7.6.1.1 171345 Sunday, April 15, 2018 Approved
Win32 OpenSSH (Universal Installer) 7.6.0.1 215207 Friday, March 2, 2018 Approved
Win32 OpenSSH (Universal Installer) 1.0.0.20180202 187403 Saturday, February 3, 2018 Approved
Win32 OpenSSH (Universal Installer) 1.0.0.20180201 10900 Thursday, February 1, 2018 Approved
Win32 OpenSSH (Universal Installer) 1.0.0.20180131 5752 Wednesday, January 31, 2018 Approved
Win32 OpenSSH (Universal Installer) 1.0.0.0 1672 Wednesday, January 31, 2018 Approved
Win32 OpenSSH (Universal Installer) 0.0.24.0 157439 Tuesday, December 5, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.23.0 44738 Monday, November 20, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.22.0 62866 Sunday, October 29, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.21.0 73583 Tuesday, October 3, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.20.20170913 62464 Thursday, September 14, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.20.0 10224 Monday, September 11, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.19.0 40248 Friday, August 25, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.18.0 50862 Thursday, July 20, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.17.0 26574 Tuesday, July 4, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.16.0 22641 Friday, June 16, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.15.20170613 2140 Wednesday, June 14, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.15.20170611 1562 Monday, June 12, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.15.0 525 Monday, June 12, 2017 Approved
Win32 OpenSSH (Universal Installer) 0.0.14.0 28389 Saturday, May 20, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.12.0 9957 Tuesday, April 18, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.11.0 7127 Friday, April 7, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.10.20170402 1584 Sunday, April 2, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.10.20170329 1428 Thursday, March 30, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.10.0 3350 Wednesday, March 15, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.9.20170313 917 Monday, March 13, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.9.20170311 929 Saturday, March 11, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.9.20170308 1374 Wednesday, March 8, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.9.20170306 762 Tuesday, March 7, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.9.20170226 2564 Sunday, February 26, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.9.20170222 1490 Wednesday, February 22, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.9.0 1709 Thursday, February 16, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.8.0 3940 Tuesday, January 31, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.7.0 3893 Monday, January 16, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.6.0 2954 Wednesday, January 4, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.5.0 520 Wednesday, January 4, 2017 Approved
Win32 OpenSSH (Microsoft Port) 0.0.4.0 6834 Wednesday, November 30, 2016 Approved
Win32 OpenSSH (Microsoft Port) 0.0.3.0 6342 Tuesday, November 8, 2016 Approved
Win32 OpenSSH (Microsoft Port) 0.0.2.20161026 4799 Wednesday, October 26, 2016 Approved
Win32 OpenSSH (Microsoft Port) 0.0.2.0 1029 Tuesday, October 25, 2016 Approved
Win32 OpenSSH (Microsoft Port) 0.0.1.0 3853 Saturday, October 1, 2016 Approved
Win32 OpenSSH (Microsoft Port) 0.0.0.901 1717 Friday, September 23, 2016 Approved
Win32 OpenSSH (Microsoft Port) 0.0.0.9 632 Wednesday, September 21, 2016 Approved

Product release notes: https://github.com/PowerShell/Win32-OpenSSH/releases/tag/v0.0.15.0

Release Notes for Chocolatey Packaging:
0.0.15.20170611
- Sets permissions for user "NT SERVICE\sshd" to write to [sshfolder]\Logs
0.0.15.0
- Calls utility script FixUserFilePermissions.ps1 (included with OpenSSH) to align setup / migrate
permissions to v.0.0.15.0 standard. Permissions are reasserted at every install / upgrade.
- A chocolatey uninstall that specifies "/DeleteConfigAndServerKeys" will fail. This is only ever used
for a completely clean uninstall - not using it means that the ssh_conf and the server key files will
remain in the openssh install folder and will need to be removed manually after taking ownership of the files.
- New switch /DisableKeyPermissionsReset disables this capability if you are managing permissions separately.
0.0.14.0
- by default sets a machine environment variable TERM=xterm, customize with /TERM switch
- updated path setting code to not make unnecessary path alterations
0.0.12.0
- ssh-lsa.dll is no longer needed and no longer configured (switch /ReleaseSSHLSAForUpgrade is ignored)
- if ssh-lsa.dll is found during upgrade a delete attempt is made - if unsuccessful (file locked), ssh-lsa.dll
will be deconfigured as an authentication package and it will be delete on the next upgrade.
0.0.11.0
- /ReleaseSSHLSAForUpgrade - switch that de-configures ssh-lsa.dll in preparation for updating it after a reboot and forced reinstall (and another reboot). See: https://github.com/DarwinJS/ChocoPackages/blob/master/openssh/readme.md
- Set-SSHKeyPermissions.ps1 - new utility for setting permissions on all existing user's authorized_keys files is placed in SSHD binaries folder (on path)
- Calls Set-SSHKeyPermissions.ps1 during install to ensure existing keys are compliant with security updates in SSH 0.0.11.0
- Fix - uninstall was not deconfiguring ssh-lsa.dll from load at startup.
- updated barebonesinstaller.ps1 to take all switches chocolatey takes
0.0.10.20170402
- fix to looking versions of installed exes for PSH 2
0.0.10.20170331
- fix to looking versions of installed exes for Nano
0.0.10.20170329
- fixed issue looking up the path of conflicting sshd service (if one exists)
- fixed problem for nano with listing of exe versions introdcued in 0.0.10.0
0.0.10.0
- displays before and after versions of all EXES in SSH install folder and ssh-lsa.dll
- readme updates for barebonesinstaller.ps1 (due to version 0.0.10.0 not sorting properly with previous versions)
- Dockerfile updates (due to version 0.0.10.0 not sorting properly with previous versions)
- Fix for Nano for barebonesinstaller.ps1 calling 7z.exe
0.0.9.20170313 - fix for Win7/Server 2008 + PSH 2 When Installing SSHServerFeature
0.0.9.20170311
- no longer overwrites sshd_conf if it already exists, unless /OverWriteSSHDConf is used
- supports setting SSHD LogLevel during install or upgrade using /SSHLogLevel
- automatically creates "logs" subfolder in install folder so that if logging is enabled
in the config file it starts without requiring a manual folder creation
0.0.9.20170308 - fix to fileinuseutiles.ps1 to not resolve path when target does not exist
0.0.9.20170306 - fix to ensure sshlsa.dll always gets installed when it should (thanks @felfert !)
0.0.9.20170226 - fix to allow barebones.ps1 to work on PSH 2 (e.g. Server 2008 R2)
0.0.9.20170222 - removal of stray file
0.0.9.0 - fix for problem detecting our install of sshd


This package has no dependencies.

Discussion for the Win32 OpenSSH (Universal Installer) Package

Ground Rules:

  • This discussion is only about Win32 OpenSSH (Universal Installer) and the Win32 OpenSSH (Universal Installer) package. If you have feedback for Chocolatey, please contact the Google Group.
  • This discussion will carry over multiple versions. If you have a comment about a particular version, please note that in your comments.
  • The maintainers of this Chocolatey Package will be notified about new comments that are posted to this Disqus thread, however, it is NOT a guarantee that you will get a response. If you do not hear back from the maintainers after posting a message below, please follow up by using the link on the left side of this page or follow this link to contact maintainers. If you still hear nothing back, please follow the package triage process.
  • Tell us what you love about the package or Win32 OpenSSH (Universal Installer), or tell us what needs improvement.
  • Share your experiences with the package, or extra configuration or gotchas that you've found.
  • If you use a url, the comment will be flagged for moderation until you've been whitelisted. Disqus moderated comments are approved on a weekly schedule if not sooner. It could take between 1-5 days for your comment to show up.
comments powered by Disqus