diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index 78a1dd14356d..f668130f0cf9 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -1419,7 +1419,7 @@ is_absolute_path(const char *path) /* return -1 - in case of failure, 0 - success */ int -create_directory_withsddl(wchar_t *path_w, wchar_t *sddl_w) +create_directory_withsddl(wchar_t *path_w, wchar_t *sddl_w, BOOL check_permissions) { if (GetFileAttributesW(path_w) == INVALID_FILE_ATTRIBUTES) { PSECURITY_DESCRIPTOR pSD = NULL; @@ -1444,12 +1444,9 @@ create_directory_withsddl(wchar_t *path_w, wchar_t *sddl_w) return -1; } } - else { + else if (check_permissions) { // directory already exists; need to confirm permissions are correct - if (check_secure_folder_permission(path_w, 1) != 0) { - error("Directory already exists but folder permissions are invalid"); - return -1; - } + check_secure_folder_permission(path_w, 1); } return 0; diff --git a/contrib/win32/win32compat/misc_internal.h b/contrib/win32/win32compat/misc_internal.h index 0761cf86f5d9..b75d9bb483b4 100644 --- a/contrib/win32/win32compat/misc_internal.h +++ b/contrib/win32/win32compat/misc_internal.h @@ -67,7 +67,7 @@ void to_lower_case(char *s); void to_wlower_case(wchar_t *s); HANDLE get_user_token(const char* user, int impersonation); int load_user_profile(HANDLE user_token, char* user); -int create_directory_withsddl(wchar_t *path, wchar_t *sddl); +int create_directory_withsddl(wchar_t *path, wchar_t *sddl, BOOL check_permissions); int is_absolute_path(const char *); int file_in_chroot_jail(HANDLE); PSID lookup_sid(const wchar_t* name_utf16, PSID psid, DWORD * psid_len); diff --git a/contrib/win32/win32compat/w32-sshfileperm.c b/contrib/win32/win32compat/w32-sshfileperm.c index baa3955a8e36..156afcd97162 100644 --- a/contrib/win32/win32compat/w32-sshfileperm.c +++ b/contrib/win32/win32compat/w32-sshfileperm.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include "inc\pwd.h" #include "sshfileperm.h" @@ -40,6 +42,12 @@ #include "misc_internal.h" #include "config.h" +#define NULL_TERMINATOR_LEN 1 +#define COMMA_SPACE_LEN 2 +#define BACKSLASH_LEN 1 + +extern int log_on_stderr; + /* * The function is to check if current user is secure to access to the file. * Check the owner of the file is one of these types: Local Administrators groups, system account, current user account @@ -178,18 +186,22 @@ check_secure_file_permission(const char *input_path, struct passwd * pw, int rea * Check the owner of the file is one of these types: Local Administrators groups or system account * Check the users have access permission to the file don't violate the following rules: 1. no user other than local administrators group and system account have write permission on the folder -* Returns 0 on success and -1 on failure +* Logs a message if the rules are violated, but does not prevent further execution */ -int +void check_secure_folder_permission(const wchar_t* path_utf16, int read_ok) { PSECURITY_DESCRIPTOR pSD = NULL; PSID owner_sid = NULL, ti_sid = NULL; PACL dacl = NULL; DWORD error_code = ERROR_SUCCESS; - BOOL is_valid_sid = FALSE, is_valid_acl = FALSE; + BOOL is_valid_sid = FALSE, is_valid_acl = FALSE, need_log_msg = FALSE, is_first = TRUE; wchar_t* bad_user = NULL; - int ret = 0; + size_t log_msg_len = (DNLEN + BACKSLASH_LEN + UNLEN) * 2 + COMMA_SPACE_LEN + NULL_TERMINATOR_LEN; + wchar_t* log_msg = (wchar_t*)malloc(log_msg_len * sizeof(wchar_t)); + if (log_msg != NULL) { + log_msg[0] = '\0'; + } /*Get the owner sid of the file.*/ if ((error_code = GetNamedSecurityInfoW(path_utf16, SE_FILE_OBJECT, @@ -197,18 +209,15 @@ check_secure_folder_permission(const wchar_t* path_utf16, int read_ok) &owner_sid, NULL, &dacl, NULL, &pSD)) != ERROR_SUCCESS) { printf("failed to retrieve the owner sid and dacl of file %S with error code: %d", path_utf16, error_code); errno = EOTHER; - ret = -1; goto cleanup; } if (((is_valid_sid = IsValidSid(owner_sid)) == FALSE) || ((is_valid_acl = IsValidAcl(dacl)) == FALSE)) { printf("IsValidSid: %d; is_valid_acl: %d", is_valid_sid, is_valid_acl); - ret = -1; goto cleanup; } if (!IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) && !IsWellKnownSid(owner_sid, WinLocalSystemSid)) { printf("Bad owner on %S", path_utf16); - ret = -1; goto cleanup; } /* @@ -224,7 +233,6 @@ check_secure_folder_permission(const wchar_t* path_utf16, int read_ok) if (!GetAce(dacl, i, ¤t_ace)) { printf("GetAce() failed"); errno = EOTHER; - ret = -1; goto cleanup; } @@ -247,15 +255,112 @@ check_secure_folder_permission(const wchar_t* path_utf16, int read_ok) continue; } else { - ret = -1; + /* collect all SIDs with write permissions */ + wchar_t resolved_trustee[UNLEN + NULL_TERMINATOR_LEN] = L"UNKNOWN"; + wchar_t resolved_trustee_domain[DNLEN + NULL_TERMINATOR_LEN] = L"UNKNOWN"; + DWORD resolved_trustee_len = _countof(resolved_trustee), resolved_trustee_domain_len = _countof(resolved_trustee_domain); + SID_NAME_USE resolved_trustee_type; + + need_log_msg = TRUE; + + if (log_msg != NULL && + LookupAccountSidW(NULL, current_trustee_sid, resolved_trustee, &resolved_trustee_len, + resolved_trustee_domain, &resolved_trustee_domain_len, &resolved_trustee_type) != 0) { + if (is_first) { + _snwprintf_s(log_msg, log_msg_len, _TRUNCATE, L"%ls\\%ls", resolved_trustee_domain, resolved_trustee); + is_first = FALSE; + } + else { + size_t currentLength = wcslen(log_msg); + size_t userLength = resolved_trustee_domain_len + BACKSLASH_LEN + resolved_trustee_len + COMMA_SPACE_LEN; + if (wcslen(log_msg) + userLength + NULL_TERMINATOR_LEN > log_msg_len) { + log_msg_len *= 2; + wchar_t* temp_log_msg = (wchar_t*)malloc(log_msg_len * sizeof(wchar_t)); + if (temp_log_msg == NULL) { + break; + } + wcscpy_s(temp_log_msg, log_msg_len, log_msg); + if (log_msg) + free(log_msg); + log_msg = temp_log_msg; + } + _snwprintf_s(log_msg + currentLength, log_msg_len - currentLength, _TRUNCATE, + L", %ls\\%ls", resolved_trustee_domain, resolved_trustee); + } + } } } + + if (need_log_msg) { + log_folder_perms_msg_etw(path_utf16, log_msg); + } cleanup: - if (bad_user) + if (bad_user) { LocalFree(bad_user); - if (pSD) + } + if (log_msg) { + free(log_msg); + } + if (pSD) { LocalFree(pSD); - if (ti_sid) + } + if (ti_sid) { free(ti_sid); - return ret; + } +} + +/* +* This function takes in the full path to the ProgramData\ssh folder +* and a string of comma-separated domain\usernames. The function converts +* the well-known built-in Administrators group sid and the Local System +* sid to their corresponding names. With these names, and the input string, +* it logs a message to the Event Viewer. If logging the detailed message fails, +* a generic log message is written to the Event Viewer instead. +*/ +void log_folder_perms_msg_etw(const wchar_t* path_utf16, wchar_t* log_msg) { + PSID adminSid = NULL; + WCHAR adminName[UNLEN + NULL_TERMINATOR_LEN]; + WCHAR adminDomain[DNLEN + NULL_TERMINATOR_LEN]; + DWORD adminNameSize = UNLEN + NULL_TERMINATOR_LEN; + DWORD adminDomainSize = DNLEN + NULL_TERMINATOR_LEN; + DWORD adminSidSize = SECURITY_MAX_SID_SIZE; + PSID systemSid = NULL; + WCHAR systemName[UNLEN + NULL_TERMINATOR_LEN]; + WCHAR systemDomain[DNLEN + NULL_TERMINATOR_LEN]; + DWORD systemNameSize = UNLEN + NULL_TERMINATOR_LEN; + DWORD systemDomainSize = DNLEN + NULL_TERMINATOR_LEN; + DWORD systemSidSize = SECURITY_MAX_SID_SIZE; + SID_NAME_USE sidType; + BOOL needLog = TRUE; + int temp_log_on_stderr = log_on_stderr; + log_on_stderr = 0; + + adminSid = (PSID)malloc(SECURITY_MAX_SID_SIZE); + if (log_msg != NULL && adminSid != NULL && + CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, adminSid, &adminSidSize) != 0 && + LookupAccountSidW(NULL, adminSid, adminName, &adminNameSize, adminDomain, &adminDomainSize, &sidType) != 0) { + systemSid = (PSID)malloc(SECURITY_MAX_SID_SIZE); + if (systemSid != NULL && + CreateWellKnownSid(WinLocalSystemSid, NULL, systemSid, &systemSidSize) != 0 && + LookupAccountSidW(NULL, systemSid, systemName, &systemNameSize, systemDomain, &systemDomainSize, &sidType) != 0) { + logit("For '%S' folder, write access is granted to the following users: %S. " + "Consider reviewing users to ensure that only %S\\%S, and the %S\\%S group, and its members, have write access.", + path_utf16, log_msg, systemDomain, systemName, adminDomain, adminName); + needLog = FALSE; + } + } + + if (needLog) { + /* log generic warning message in unlikely case that lookup for either well-known SID fails or user list is empty */ + logit("for '%S' folder, consider downgrading permissions for any users with unnecessary write access.", path_utf16); + } + + log_on_stderr = temp_log_on_stderr; + + if (adminSid) { + free(adminSid); + } + if (systemSid) { + free(systemSid); + } } diff --git a/contrib/win32/win32compat/wmain_sshd.c b/contrib/win32/win32compat/wmain_sshd.c index 21cc24b04c88..dacdf14e7d11 100644 --- a/contrib/win32/win32compat/wmain_sshd.c +++ b/contrib/win32/win32compat/wmain_sshd.c @@ -135,7 +135,7 @@ create_prgdata_ssh_folder() wchar_t ssh_cfg_dir[PATH_MAX] = { 0, }; wcscpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), __wprogdata); wcscat_s(ssh_cfg_dir, _countof(ssh_cfg_dir), L"\\ssh"); - if (create_directory_withsddl(ssh_cfg_dir, L"O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)") < 0) { + if (create_directory_withsddl(ssh_cfg_dir, L"O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)", TRUE) < 0) { printf("failed to create %S", ssh_cfg_dir); exit(255); } @@ -144,7 +144,7 @@ create_prgdata_ssh_folder() wchar_t logs_dir[PATH_MAX] = { 0, }; wcscat_s(logs_dir, _countof(logs_dir), ssh_cfg_dir); wcscat_s(logs_dir, _countof(logs_dir), L"\\logs"); - if (create_directory_withsddl(logs_dir, L"O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)") < 0) { + if (create_directory_withsddl(logs_dir, L"O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)", FALSE) < 0) { printf("failed to create %S", logs_dir); exit(255); } diff --git a/log.c b/log.c index d70872492a45..619334a10239 100644 --- a/log.c +++ b/log.c @@ -54,7 +54,11 @@ #include "match.h" static LogLevel log_level = SYSLOG_LEVEL_INFO; +#ifdef WINDOWS +int log_on_stderr = 1; +#else static int log_on_stderr = 1; +#endif /* WINDOWS */ static int log_stderr_fd = STDERR_FILENO; static int log_facility = LOG_AUTH; static const char *argv0; diff --git a/regress/pesterTests/Setup.Tests.ps1 b/regress/pesterTests/Setup.Tests.ps1 index 96074759ce27..2c663e394faf 100644 --- a/regress/pesterTests/Setup.Tests.ps1 +++ b/regress/pesterTests/Setup.Tests.ps1 @@ -8,12 +8,12 @@ Describe "Setup Tests" -Tags "Setup" { if($OpenSSHTestInfo -eq $null) { Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments." - } - + } + $windowsInBox = $OpenSSHTestInfo["WindowsInBox"] $binPath = $OpenSSHTestInfo["OpenSSHBinPath"] - $dataPath = Join-path $env:ProgramData ssh - + $dataPath = Join-path $env:ProgramData ssh + $systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid) $adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid) $usersSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinUsersSid) @@ -34,24 +34,24 @@ Describe "Setup Tests" -Tags "Setup" { ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__) $RegReadKeyPerm = ([System.UInt32] [System.Security.AccessControl.RegistryRights]::ReadKey.value__) - $RegFullControlPerm = [System.UInt32] [System.Security.AccessControl.RegistryRights]::FullControl.value__ + $RegFullControlPerm = [System.UInt32] [System.Security.AccessControl.RegistryRights]::FullControl.value__ #only validate owner and ACEs of the registry function ValidateRegistryACL { param([string]$RegPath, $Ownersid = $adminsSid, $IdAcls) - Test-Path -Path $RegPath | Should Be $true + Test-Path -Path $RegPath | Should Be $true $myACL = Get-ACL $RegPath $OwnerSid = Get-UserSid -User $myACL.Owner $OwnerSid.Equals($Ownersid) | Should Be $true $myACL.Access | Should Not Be $null - $CAPABILITY_SID = "S-1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-3232135806-4053264122-3456934681" + $CAPABILITY_SID = "S-1-15-3-1024-1065365936-1281604716-3511738428-1654721687-432734479-3232135806-4053264122-3456934681" $nonPropagate = $myACL.Access | ? {($_.PropagationFlags -eq ([System.Security.AccessControl.PropagationFlags]::None)) -and ($_.IdentityReference -ine $CAPABILITY_SID)} foreach ($a in $nonPropagate) { $findItem = $IdAcls | ? { ($a.IdentityReference -eq (Get-UserAccount -UserSid ($_.Identity))) -and ` ($a.IsInherited -eq $_.IsInherited) -and ` - ($a.AccessControlType -eq ([System.Security.AccessControl.AccessControlType]::Allow)) -and ` + ($a.AccessControlType -eq ([System.Security.AccessControl.AccessControlType]::Allow)) -and ` (([System.Int32]$a.RegistryRights.value__) -eq ($_.RegistryRights)) } $findItem | Should Not Be $null @@ -60,11 +60,11 @@ Describe "Setup Tests" -Tags "Setup" { foreach ($expected in $IdAcls) { $findItem = $nonPropagate | ? { ((Get-UserAccount -UserSid ($expected.Identity)) -eq $_.IdentityReference) -and ` - ($expected.IsInherited -eq $_.IsInherited) -and ` + ($expected.IsInherited -eq $_.IsInherited) -and ` ($expected.RegistryRights -eq ([System.Int32]$_.RegistryRights.value__)) } $findItem | Should Not Be $null - } + } } #only validate owner and ACEs of the file @@ -86,8 +86,8 @@ Describe "Setup Tests" -Tags "Setup" { $myACL = Get-ACL $FilePath $currentOwnerSid = Get-UserSid -User $myACL.Owner - if(-not $windowsInBox) {return} - $currentOwnerSid.Equals($OwnerSid) | Should Be $true + if(-not $windowsInBox) {return} + $currentOwnerSid.Equals($OwnerSid) | Should Be $true $myACL.Access | Should Not Be $null if($IsDirectory) { @@ -111,7 +111,7 @@ Describe "Setup Tests" -Tags "Setup" { if($id -eq $null) { $idRefShortValue = ($a.IdentityReference.Value).split('\')[-1] - $id = Get-UserSID -User $idRefShortValue + $id = Get-UserSID -User $idRefShortValue } $identities -contains $id | Should be $true @@ -127,12 +127,12 @@ Describe "Setup Tests" -Tags "Setup" { else { ([System.UInt32]$a.FileSystemRights.value__) | Should Be $FSReadAndExecutePerm - } + } break; } {@($usersSid, $allApplicationPackagesSid, $allRestrictedApplicationPackagesSid, $authenticatedUserSid) -contains $_} - { - ([System.UInt32]$a.FileSystemRights.value__) | Should Be $FSReadAndExecutePerm + { + ([System.UInt32]$a.FileSystemRights.value__) | Should Be $FSReadAndExecutePerm break; } $trustedInstallerSid @@ -141,7 +141,7 @@ Describe "Setup Tests" -Tags "Setup" { break; } } - + $a.AccessControlType | Should Be ([System.Security.AccessControl.AccessControlType]::Allow) if($IsDirectory) { @@ -154,8 +154,8 @@ Describe "Setup Tests" -Tags "Setup" { } $a.PropagationFlags | Should Be ([System.Security.AccessControl.PropagationFlags]::None) } - } - } + } + } Context "$tC - Validate Openssh binary files" { @@ -230,7 +230,7 @@ Describe "Setup Tests" -Tags "Setup" { } ) } - AfterAll{$tC++} + AfterAll{$tC++} AfterEach { $tI++ } It "$tC.$tI - Validate Openssh binary files--" -TestCases:$binaries{ @@ -238,7 +238,7 @@ Describe "Setup Tests" -Tags "Setup" { ValidateFileSystem -FilePath (join-path $binPath $Name) } It "$tC.$tI - Validate Openssh script files--" -TestCases:$dataFile { - param([string]$Name, [boolean]$IsDirectory = $false) + param([string]$Name, [boolean]$IsDirectory = $false) if(-not $WindowsInbox) { ValidateFileSystem -FilePath (join-path $binPath $Name) } } @@ -248,17 +248,17 @@ Describe "Setup Tests" -Tags "Setup" { { Start-Service sshd } - + ValidateFileSystem -FilePath (join-path $dataPath $Name) -IsDirectory $IsDirectory -OwnerSid $adminsSid -IsDataFile } - } - + } + Context "$tC - Validate Openssh registry entries" { BeforeAll { $tI=1 $servicePath = "HKLM:\SYSTEM\ControlSet001\Services" $opensshRegPath = "HKLM:\SOFTWARE\OpenSSH" - + $opensshACLs = @( @{ Identity=$systemSid @@ -271,7 +271,7 @@ Describe "Setup Tests" -Tags "Setup" { IsInherited = $false RegistryRights = $RegFullControlPerm PropagationFlags = "None" - }, + }, @{ Identity=$authenticatedUserSid IsInherited = $false @@ -294,9 +294,9 @@ Describe "Setup Tests" -Tags "Setup" { PropagationFlags = "None" } ) - } + } AfterAll{$tC++} - AfterEach { $tI++ } + AfterEach { $tI++ } It "$tC.$tI - Validate Registry key ssh-agent\Description" { $p = Get-ItemPropertyValue (Join-Path $servicePath "ssh-agent") -Name "Description" @@ -317,10 +317,10 @@ Describe "Setup Tests" -Tags "Setup" { It "$tC.$tI - Validate Registry key ssh-agent\ObjectName" { $p = Get-ItemPropertyValue (Join-Path $servicePath "ssh-agent") -Name "ObjectName" $p | Should Be "LocalSystem" - } + } It "$tC.$tI - Validate Registry key ssh-agent\Start" { - $p = Get-ItemPropertyValue (Join-Path $servicePath "ssh-agent") -Name "Start" + $p = Get-ItemPropertyValue (Join-Path $servicePath "ssh-agent") -Name "Start" if($windowsInBox) { $p | Should Be 4 } @@ -332,12 +332,12 @@ Describe "Setup Tests" -Tags "Setup" { It "$tC.$tI - Validate Registry key ssh-agent\Type" { $p = Get-ItemPropertyValue (Join-Path $servicePath "ssh-agent") -Name "Type" $p | Should Be 16 - } + } - It "$tC.$tI - Validate Registry key to ssh-agent\Security\Security" { + It "$tC.$tI - Validate Registry key to ssh-agent\Security\Security" { $p = Get-ItemPropertyValue (Join-Path $servicePath "ssh-agent\Security") -Name Security $p.Gettype() | Should Be byte[] - } + } It "$tC.$tI - Validate Registry key sshd\Description" { $p = Get-ItemPropertyValue (Join-Path $servicePath "sshd") -Name "Description" @@ -356,17 +356,17 @@ Describe "Setup Tests" -Tags "Setup" { } It "$tC.$tI - Validate Registry key sshd\ObjectName" { - $p = Get-ItemPropertyValue (Join-Path $servicePath "sshd") -Name "ObjectName" + $p = Get-ItemPropertyValue (Join-Path $servicePath "sshd") -Name "ObjectName" $p | Should Be "LocalSystem" - } + } It "$tC.$tI - Validate Registry key sshd\Start" { - $p = Get-ItemPropertyValue (Join-Path $servicePath "sshd") -Name "Start" + $p = Get-ItemPropertyValue (Join-Path $servicePath "sshd") -Name "Start" $p | Should Be 3 } It "$tC.$tI - Validate Registry key sshd\Type" { - $p = Get-ItemPropertyValue (Join-Path $servicePath "sshd") -Name "Type" + $p = Get-ItemPropertyValue (Join-Path $servicePath "sshd") -Name "Type" $p | Should Be 16 } @@ -383,18 +383,18 @@ Describe "Setup Tests" -Tags "Setup" { { Start-Service ssh-agent ValidateRegistryACL -RegPath $agentPath -IdAcls $opensshAgentACLs - } + } } } Context "$tC - Validate service settings" { - BeforeAll { + BeforeAll { $tI=1 - } + } AfterAll{$tC++} AfterEach { $tI++ } - It "$tC.$tI - Validate properties of ssh-agent service" { + It "$tC.$tI - Validate properties of ssh-agent service" { $sshdSvc = Get-service ssh-agent if($windowsInBox) { $sshdSvc.StartType | Should Be ([System.ServiceProcess.ServiceStartMode]::Disabled) @@ -411,7 +411,7 @@ Describe "Setup Tests" -Tags "Setup" { ($sshdSvc.RequiredServices).Count | Should Be 0 } - It "$tC.$tI - Validate properties of sshd service" { + It "$tC.$tI - Validate properties of sshd service" { $sshdSvc = Get-service sshd $sshdSvc.StartType | Should Be ([System.ServiceProcess.ServiceStartMode]::Manual) $sshdSvc.ServiceType | Should Be ([System.ServiceProcess.ServiceType]::Win32OwnProcess) @@ -422,7 +422,7 @@ Describe "Setup Tests" -Tags "Setup" { ($sshdSvc.ServicesDependedOn).Count | Should Be 0 ($sshdSvc.RequiredServices).Count | Should Be 0 } - + It "$tC.$tI - Validate RequiredPrivileges of ssh-agent" { $expected = @("SeAssignPrimaryTokenPrivilege", "SeTcbPrivilege", "SeBackupPrivilege", "SeRestorePrivilege", "SeImpersonatePrivilege") $a = sc.exe qprivs ssh-agent 256 @@ -449,7 +449,7 @@ Describe "Setup Tests" -Tags "Setup" { } } - It "$tC.$tI - Validate security access to ssh-agent service" { + It "$tC.$tI - Validate security access to ssh-agent service" { $a = @(sc.exe sdshow ssh-agent) $b = $a[-1] -split "[D|S]:" @@ -460,19 +460,19 @@ Describe "Setup Tests" -Tags "Setup" { $actual_dacl_aces = $dacl_aces | ? { -not [string]::IsNullOrWhiteSpace($_) } $expected_dacl_aces | % { - $actual_dacl_aces -contains $_ | Should be $true + $actual_dacl_aces -contains $_ | Should be $true } $actual_dacl_aces | % { $expected_dacl_aces -contains $_ | Should be $true } <# ignore sacl for now - if($c.Count -gt 1) { - $c[1] | Should Be "(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)" + if($c.Count -gt 1) { + $c[1] | Should Be "(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)" }#> } - It "$tC.$tI - Validate security access to sshd service" { + It "$tC.$tI - Validate security access to sshd service" { $a = @(sc.exe sdshow sshd) $b = $a[-1] -split "[D|S]:" @@ -490,8 +490,8 @@ Describe "Setup Tests" -Tags "Setup" { } <# ignore sacl for now - if($c.Count -gt 1) { - $c[1] | Should Be "(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)" + if($c.Count -gt 1) { + $c[1] | Should Be "(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)" }#> } } @@ -501,12 +501,12 @@ Describe "Setup Tests" -Tags "Setup" { $firwallRuleName = "OpenSSH-Server-In-TCP" $tI=1 } - + AfterAll{$tC++} AfterEach { $tI++ } It "$tC.$tI - Validate Firewall settings" -skip:(!$windowsInBox) { - $rule = Get-NetFirewallRule -Name $firwallRuleName + $rule = Get-NetFirewallRule -Name $firwallRuleName $rule.Group | Should BeLike "OpenSSH*" $rule.Description | Should BeLike "*OpenSSH*" $rule.DisplayName | Should BeLike "OpenSSH*" @@ -519,6 +519,54 @@ Describe "Setup Tests" -Tags "Setup" { $fwportFilter.Protocol | Should Be 'TCP' $fwportFilter.LocalPort | Should Be 22 $fwportFilter.RemotePort | Should Be 'Any' - } + } + } + + Context "$tC - Validate SSHD service startup" { + BeforeAll { + $tI=1 + $sshFolderPath = Join-Path $env:ProgramData "ssh" + $sshACL = $null + if (Test-Path -Path $sshFolderPath) { + $sshACL = Get-Acl $sshFolderPath + } + $logFolderPath = Join-Path $env:ProgramData "ssh" "logs" + $logACL = $null + if (Test-Path -Path $logFolderPath) { + $logACL = Get-Acl $logFolderPath + } + } + AfterAll { + $tC++ + if ($logACL -eq $null) { + Remove-Item -Path $logFolderPath -Recurse -Force + } + if ($sshACL -eq $null) { + Remove-Item -Path $sshFolderPath -Recurse -Force + } + } + AfterEach { + $tI++ + net stop sshd + if ($sshACL -ne $null) { + Set-Acl -Path $sshFolderPath -AclObject $sshACL + } + if ($logACL -ne $null) { + Set-Acl -Path $logFolderPath -AclObject $logACL + } + } + + It "$tC.$tI - SSHD starts up successfully when Authenticated Users have read control over log folder" { + if (-not (Test-Path -Path $logFolderPath)) { + New-Item -Path $logFolderPath -ItemType Directory -Force + } + # Set ACLs on the folder + $acl = Get-Acl $logFolderPath + $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($authenticatedUserSid, "ReadAndExecute", "Allow") + $acl.SetAccessRule($accessRule) + Set-Acl -Path $logFolderPath -AclObject $acl + net start sshd + $LASTEXITCODE | Should Be 0 + } } } diff --git a/sshfileperm.h b/sshfileperm.h index 1604139aafc6..1e2a68473939 100644 --- a/sshfileperm.h +++ b/sshfileperm.h @@ -26,5 +26,6 @@ #define _SSH_FILE_PERM_H int check_secure_file_permission(const char *, struct passwd *, int); -int check_secure_folder_permission(const wchar_t*, int); +void check_secure_folder_permission(const wchar_t*, int); +void log_folder_perms_msg_etw(const wchar_t*, wchar_t*); #endif /* _SSH_FILE_PERM_H */