This commit is contained in:
Yanbing 2017-02-14 13:43:06 -08:00 committed by Manoj Ampalam
parent c4a9f83682
commit 8e9236b03b
16 changed files with 558 additions and 141 deletions

View File

@ -244,7 +244,6 @@ int sys_auth_passwd(Authctxt *authctxt, const char *password)
if (sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE) != 0 || if (sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE) != 0 ||
sshbuf_put_cstring(msg, PASSWD_AUTH_REQUEST) != 0 || sshbuf_put_cstring(msg, PASSWD_AUTH_REQUEST) != 0 ||
sshbuf_put_cstring(msg, authctxt->pw->pw_name) != 0 || sshbuf_put_cstring(msg, authctxt->pw->pw_name) != 0 ||
sshbuf_put_cstring(msg, authctxt->pw->pw_domain) != 0 ||
sshbuf_put_cstring(msg, password) != 0 || sshbuf_put_cstring(msg, password) != 0 ||
ssh_request_reply(auth_sock, msg, msg) != 0 || ssh_request_reply(auth_sock, msg, msg) != 0 ||
sshbuf_get_u32(msg, &token) != 0) { sshbuf_get_u32(msg, &token) != 0) {

View File

@ -196,7 +196,6 @@ userauth_pubkey(Authctxt *authctxt)
(r = sshkey_to_blob(key, &blob, &blen)) != 0 || (r = sshkey_to_blob(key, &blob, &blen)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0 || (r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_cstring(msg, authctxt->pw->pw_name)) != 0 || (r = sshbuf_put_cstring(msg, authctxt->pw->pw_name)) != 0 ||
(r = sshbuf_put_cstring(msg, authctxt->pw->pw_domain)) != 0 ||
(r = sshbuf_put_string(msg, sig, slen)) != 0 || (r = sshbuf_put_string(msg, sig, slen)) != 0 ||
(r = sshbuf_put_string(msg, buffer_ptr(&b), buffer_len(&b))) != 0 || (r = sshbuf_put_string(msg, buffer_ptr(&b), buffer_len(&b))) != 0 ||
(r = ssh_request_reply(auth_sock, msg, msg)) != 0 || (r = ssh_request_reply(auth_sock, msg, msg)) != 0 ||

View File

@ -3,7 +3,6 @@ Import-Module $PSScriptRoot\build.psm1 -Force -DisableNameChecking
$repoRoot = Get-RepositoryRoot $repoRoot = Get-RepositoryRoot
$script:logFile = join-path $repoRoot.FullName "appveyor.log" $script:logFile = join-path $repoRoot.FullName "appveyor.log"
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log" $script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
$testfailed = $false
<# <#
Called by Write-BuildMsg to write to the build log, if it exists. Called by Write-BuildMsg to write to the build log, if it exists.
@ -241,6 +240,13 @@ function Install-TestDependencies
[CmdletBinding()] [CmdletBinding()]
param () param ()
# Install chocolatey
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
{
Write-Log -Message "Chocolatey not present. Installing chocolatey."
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:logFile
}
$isModuleAvailable = Get-Module 'Pester' -ListAvailable $isModuleAvailable = Get-Module 'Pester' -ListAvailable
if (-not ($isModuleAvailable)) if (-not ($isModuleAvailable))
{ {
@ -495,42 +501,14 @@ function Deploy-OpenSSHTests
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot [System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
#copy all pester tests
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests" $sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Include *.ps1,*.psm1 -Force -ErrorAction Stop Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Include *.ps1,*.psm1, sshd_config -Force -ErrorAction Stop
#copy all unit tests.
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration" $sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Exclude ssh-agent.exe, sshd.exe -Force -ErrorAction Stop Copy-Item -Path "$sourceDir\unittest-*" -Destination $OpenSSHTestDir -Force -ErrorAction Stop
#restart the service to use the test copy of sshd_config
Restart-Service sshd
$sshdConfigFile = "$OpenSSHTestDir\sshd_config"
if (-not (Test-Path -Path $sshdConfigFile -PathType Leaf))
{
Write-BuildMessage "Installation dependencies: $OpenSSHTestDir\sshd_config is missing in the folder" -Category Error
throw "$OpenSSHTestDir\sshd_config is missing in the folder"
}
if ($env:DebugMode)
{
$strToReplace = "#LogLevel INFO"
(Get-Content $sshdConfigFile).Replace($strToReplace,"LogLevel Debug3") | Set-Content $sshdConfigFile
}
if(-not ($env:psPath))
{
$psCorePath = GetLocalPSCorePath
Set-BuildVariable -Name psPath -Value $psCorePath
}
$strToReplace = "Subsystem sftp sftp-server.exe"
if($env:psPath)
{
$strNewsubSystem = @"
Subsystem sftp sftp-server.exe
Subsystem powershell $env:psPath
"@
}
(Get-Content $sshdConfigFile).Replace($strToReplace, $strNewsubSystem) | Set-Content $sshdConfigFile
} }

View File

@ -152,17 +152,6 @@ function Start-SSHBootstrap
{ {
Write-BuildMsg -AsInfo -Message "Chocolatey not present. Installing chocolatey." -Silent:$silent Write-BuildMsg -AsInfo -Message "Chocolatey not present. Installing chocolatey." -Silent:$silent
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:BuildLogFile Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:BuildLogFile
if (-not ($machinePath.ToLower().Contains($chocolateyPath.ToLower())))
{
Write-BuildMsg -AsVerbose -Message "Adding $chocolateyPath to Path environment variable" -Silent:$silent
$newMachineEnvironmentPath += ";$chocolateyPath"
$env:Path += ";$chocolateyPath"
}
else
{
Write-BuildMsg -AsVerbose -Message "$chocolateyPath already present in Path environment variable" -Silent:$silent
}
} }
# Add git\cmd to the path # Add git\cmd to the path
@ -231,7 +220,7 @@ function Start-SSHBootstrap
# Install Windows 8.1 SDK # Install Windows 8.1 SDK
$packageName = "windows-sdk-8.1" $packageName = "windows-sdk-8.1"
$sdkPath = "C:\Program Files (x86)\Windows Kits\8.1\bin\x86\register_app.vbs" $sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs"
if (-not (Test-Path -Path $sdkPath)) if (-not (Test-Path -Path $sdkPath))
{ {
@ -264,7 +253,7 @@ function Start-SSHBootstrap
Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent
if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false) if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false)
{ {
Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at" + $script:vcPath Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at$script:vcPath, which means some required develop kits are missing on the machine."
} }
} }

View File

@ -202,6 +202,7 @@
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\ssh-pubkey\ssh-pubkeydefs.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\ssh-pubkey\ssh-pubkeydefs.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\agent-request.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\agent-request.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\agent.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\agent.h" />
<ClInclude Include="$(OpenSSH-Src-Path)groupaccess.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="$(OpenSSH-Src-Path)\auth.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\auth.c" />
@ -212,8 +213,9 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\agentconfig.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\agentconfig.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\connection.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\connection.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\keyagent-request.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\keyagent-request.c" />
<ClCompile Include="..\..\..\auth-options.c" /> <ClCompile Include="$(OpenSSH-Src-Path)auth-options.c" />
<ClCompile Include="..\..\..\auth2-pubkey.c" /> <ClCompile Include="$(OpenSSH-Src-Path)auth2-pubkey.c" />
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="version.rc" /> <ResourceCompile Include="version.rc" />

View File

@ -248,6 +248,7 @@
<ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c" /> <ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c" />
<ClCompile Include="$(OpenSSH-Src-Path)sshpty.c" /> <ClCompile Include="$(OpenSSH-Src-Path)sshpty.c" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c" /> <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c" />
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="version.rc" /> <ResourceCompile Include="version.rc" />

View File

@ -150,6 +150,9 @@
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c"> <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="version.rc"> <ResourceCompile Include="version.rc">

View File

@ -14,7 +14,6 @@
struct passwd { struct passwd {
char *pw_name; /* user's login name */ char *pw_name; /* user's login name */
char *pw_domain; /* user's domain name */
char *pw_passwd; /* password? */ char *pw_passwd; /* password? */
char *pw_gecos; /* ??? */ char *pw_gecos; /* ??? */
uid_t pw_uid; /* numerical user ID */ uid_t pw_uid; /* numerical user ID */

View File

@ -90,31 +90,6 @@ innetgr(const char *netgroup, const char *host, const char *user, const char *do
return -1; return -1;
} }
/* groupaccess.c*/
int
ga_init(const char *user, gid_t base)
{
return -1;
}
int
ga_match(char * const *groups, int n)
{
return -1;
}
int
ga_match_pattern_list(const char *group_pattern)
{
return -1;
}
void
ga_free(void)
{
return;
}
int int
chroot(const char *path) chroot(const char *path)
{ {

View File

@ -82,13 +82,10 @@ reset_pw()
free(pw.pw_name); free(pw.pw_name);
if (pw.pw_dir) if (pw.pw_dir)
free(pw.pw_dir); free(pw.pw_dir);
if (pw.pw_domain)
free(pw.pw_domain);
if (pw.pw_sid) if (pw.pw_sid)
free(pw.pw_sid); free(pw.pw_sid);
pw.pw_name = NULL; pw.pw_name = NULL;
pw.pw_dir = NULL; pw.pw_dir = NULL;
pw.pw_domain = NULL;
pw.pw_sid = NULL; pw.pw_sid = NULL;
} }
@ -97,14 +94,14 @@ get_passwd(const char *user_utf8, LPWSTR user_sid)
{ {
struct passwd *ret = NULL; struct passwd *ret = NULL;
wchar_t *user_utf16 = NULL, *uname_utf16, *udom_utf16, *tmp; wchar_t *user_utf16 = NULL, *uname_utf16, *udom_utf16, *tmp;
char *uname_utf8 = NULL, *udom_utf8 = NULL, *pw_home_utf8 = NULL, *user_sid_utf8 = NULL; char *uname_utf8 = NULL, *uname_upn = NULL, *udom_utf8 = NULL, *pw_home_utf8 = NULL, *user_sid_utf8 = NULL;
LPBYTE user_info = NULL; LPBYTE user_info = NULL;
LPWSTR user_sid_local = NULL; LPWSTR user_sid_local = NULL;
wchar_t reg_path[PATH_MAX], profile_home[PATH_MAX]; wchar_t reg_path[PATH_MAX], profile_home[PATH_MAX];
HKEY reg_key = 0; HKEY reg_key = 0;
int tmp_len = PATH_MAX; int tmp_len = PATH_MAX;
PDOMAIN_CONTROLLER_INFOW pdc = NULL; PDOMAIN_CONTROLLER_INFOW pdc = NULL;
DWORD dsStatus; DWORD dsStatus, uname_upn_len = 0;;
errno = 0; errno = 0;
reset_pw(); reset_pw();
@ -169,10 +166,23 @@ get_passwd(const char *user_utf8, LPWSTR user_sid)
goto done; goto done;
} }
pw.pw_name = uname_utf8; uname_upn_len = strlen(uname_utf8) + 1;
uname_utf8 = NULL; if (udom_utf8)
pw.pw_domain = udom_utf8; uname_upn_len += strlen(udom_utf8) + 1;
udom_utf8 = NULL;
if ((uname_upn = malloc(uname_upn_len)) == NULL) {
errno = ENOMEM;
goto done;
}
memcpy(uname_upn, uname_utf8, strlen(uname_utf8) + 1);
if (udom_utf8) {
/* TODO - get domain FQDN */
uname_upn[strlen(uname_utf8)] = '@';
memcpy(uname_upn + strlen(uname_utf8) + 1, udom_utf8, strlen(udom_utf8) + 1);
}
pw.pw_name = uname_upn;
uname_upn = NULL;
pw.pw_dir = pw_home_utf8; pw.pw_dir = pw_home_utf8;
pw_home_utf8 = NULL; pw_home_utf8 = NULL;
pw.pw_sid = user_sid_utf8; pw.pw_sid = user_sid_utf8;
@ -184,6 +194,8 @@ done:
free(user_utf16); free(user_utf16);
if (uname_utf8) if (uname_utf8)
free(uname_utf8); free(uname_utf8);
if (uname_upn)
free(uname_upn);
if (udom_utf8) if (udom_utf8)
free(udom_utf8); free(udom_utf8);
if (pw_home_utf8) if (pw_home_utf8)

View File

@ -38,6 +38,7 @@
#include "agent.h" #include "agent.h"
#include "agent-request.h" #include "agent-request.h"
#include "key.h" #include "key.h"
#include "inc\utf.h"
static void static void
InitLsaString(LSA_STRING *lsa_string, const char *str) InitLsaString(LSA_STRING *lsa_string, const char *str)
@ -105,7 +106,7 @@ LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
#define MAX_PW_LEN 64 #define MAX_PW_LEN 64
static HANDLE static HANDLE
generate_user_token(wchar_t* user, wchar_t* domain) { generate_user_token(wchar_t* user_cpn) {
HANDLE lsa_handle = 0, token = 0; HANDLE lsa_handle = 0, token = 0;
LSA_OPERATIONAL_MODE mode; LSA_OPERATIONAL_MODE mode;
ULONG auth_package_id; ULONG auth_package_id;
@ -120,7 +121,7 @@ generate_user_token(wchar_t* user, wchar_t* domain) {
DWORD cbProfile; DWORD cbProfile;
BOOL domain_user; BOOL domain_user;
domain_user = (*domain != L'\0') ? TRUE : FALSE; domain_user = wcschr(user_cpn, L'@')? TRUE : FALSE;
InitLsaString(&logon_process_name, "ssh-agent"); InitLsaString(&logon_process_name, "ssh-agent");
if (domain_user) if (domain_user)
@ -137,10 +138,6 @@ generate_user_token(wchar_t* user, wchar_t* domain) {
if (domain_user) { if (domain_user) {
KERB_S4U_LOGON *s4u_logon; KERB_S4U_LOGON *s4u_logon;
wchar_t user_cpn[MAX_USER_LEN + 1 + MAX_FQDN_LEN + 1];
memcpy(user_cpn, user, wcslen(user) * 2);
user_cpn[wcslen(user)] = L'@';
memcpy(user_cpn + wcslen(user) + 1, domain, wcslen(domain) * 2 + 2);
logon_info_size = sizeof(KERB_S4U_LOGON); logon_info_size = sizeof(KERB_S4U_LOGON);
logon_info_size += (wcslen(user_cpn) * 2 + 2); logon_info_size += (wcslen(user_cpn) * 2 + 2);
logon_info = malloc(logon_info_size); logon_info = malloc(logon_info_size);
@ -157,11 +154,11 @@ generate_user_token(wchar_t* user, wchar_t* domain) {
s4u_logon->ClientRealm.MaximumLength = 0; s4u_logon->ClientRealm.MaximumLength = 0;
s4u_logon->ClientRealm.Buffer = 0; s4u_logon->ClientRealm.Buffer = 0;
} else { } else {
logon_info_size = (wcslen(user) + 1)*sizeof(wchar_t); logon_info_size = (wcslen(user_cpn) + 1)*sizeof(wchar_t);
logon_info = malloc(logon_info_size); logon_info = malloc(logon_info_size);
if (logon_info == NULL) if (logon_info == NULL)
goto done; goto done;
memcpy(logon_info, user, logon_info_size); memcpy(logon_info, user_cpn, logon_info_size);
} }
memcpy(sourceContext.SourceName,"sshagent", sizeof(sourceContext.SourceName)); memcpy(sourceContext.SourceName,"sshagent", sizeof(sourceContext.SourceName));
@ -201,36 +198,35 @@ done:
/* TODO - SecureZeroMemory password */ /* TODO - SecureZeroMemory password */
int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) { int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
char *user = NULL, *domain = NULL, *pwd = NULL; char *user = NULL, *domain = NULL, *pwd = NULL;
wchar_t userW_buf[MAX_USER_LEN], domainW_buf[MAX_FQDN_LEN], pwdW_buf[MAX_PW_LEN]; size_t user_len, pwd_len;
wchar_t *userW = userW_buf, *domW = domainW_buf, *pwdW = pwdW_buf, *tmp; wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *pwd_utf16 = NULL, *tmp;
size_t user_len = 0, domain_len = 0, pwd_len = 0, dom_len = 0;
int r = -1; int r = -1;
HANDLE token = 0, dup_token, client_proc = 0; HANDLE token = 0, dup_token, client_proc = 0;
ULONG client_pid; ULONG client_pid;
if (sshbuf_get_cstring(request, &user, &user_len) != 0 || if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
sshbuf_get_cstring(request, &domain, &domain_len) != 0 ||
sshbuf_get_cstring(request, &pwd, &pwd_len) != 0 || sshbuf_get_cstring(request, &pwd, &pwd_len) != 0 ||
user_len == 0 || user_len == 0 ||
pwd_len == 0 || pwd_len == 0 ||
user_len > MAX_USER_LEN || user_len > MAX_USER_LEN + MAX_FQDN_LEN ||
domain_len > MAX_FQDN_LEN ||
pwd_len > MAX_PW_LEN) { pwd_len > MAX_PW_LEN) {
debug("bad password auth request"); debug("bad password auth request");
goto done; goto done;
} }
userW[0] = L'\0'; if ((user_utf16 = utf8_to_utf16(user)) == NULL ||
domW[0] = L'\0'; (pwd_utf16 = utf8_to_utf16(pwd)) == NULL) {
if ((MultiByteToWideChar(CP_UTF8, 0, user, user_len + 1, userW, MAX_USER_LEN) == 0) || debug("out of memory");
(domain_len != 0 && MultiByteToWideChar(CP_UTF8, 0, domain, domain_len + 1, domW, MAX_FQDN_LEN) == 0) ||
(MultiByteToWideChar(CP_UTF8, 0, pwd, pwd_len + 1, pwdW, MAX_PW_LEN) == 0)) {
debug("unable to convert user (%s) or password to UTF-16", user);
goto done; goto done;
} }
if (LogonUserW(userW, domW, pwdW, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) { if ((tmp = wcschr(user_utf16, L'@') ) != NULL ) {
debug("failed to logon user"); udom_utf16 = tmp + 1;
*tmp = L'\0';
}
if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
debug("failed to logon user: %ls domain: %ls", user_utf16, udom_utf16);
goto done; goto done;
} }
@ -243,7 +239,7 @@ int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response
} }
con->auth_token = token; con->auth_token = token;
LoadProfile(con, userW, domW); LoadProfile(con, user_utf16, udom_utf16);
r = 0; r = 0;
done: done:
/* TODO Fix this hacky protocol*/ /* TODO Fix this hacky protocol*/
@ -254,6 +250,10 @@ done:
free(user); free(user);
if (pwd) if (pwd)
free(pwd); free(pwd);
if (user_utf16)
free(user_utf16);
if (pwd_utf16)
free(pwd_utf16);
if (client_proc) if (client_proc)
CloseHandle(client_proc); CloseHandle(client_proc);
@ -262,22 +262,19 @@ done:
int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) { int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
int r = -1; int r = -1;
char *key_blob, *user, *domain, *usernameWithDomain, *sig, *blob; char *key_blob, *user, *sig, *blob;
size_t key_blob_len, user_len, domain_len, sig_len, blob_len; size_t key_blob_len, user_len, sig_len, blob_len;
struct sshkey *key = NULL; struct sshkey *key = NULL;
HANDLE token = NULL, restricted_token = NULL, dup_token = NULL, client_proc = NULL; HANDLE token = NULL, restricted_token = NULL, dup_token = NULL, client_proc = NULL;
wchar_t wuser[MAX_USER_LEN], wdomain[MAX_FQDN_LEN]; wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *tmp;
PWSTR wuser_home = NULL; PWSTR wuser_home = NULL;
ULONG client_pid; ULONG client_pid;
LUID_AND_ATTRIBUTES priv_to_delete[1]; LUID_AND_ATTRIBUTES priv_to_delete[1];
user = NULL; user = NULL;
domain = NULL;
if (sshbuf_get_string_direct(request, &key_blob, &key_blob_len) != 0 || if (sshbuf_get_string_direct(request, &key_blob, &key_blob_len) != 0 ||
sshbuf_get_cstring(request, &user, &user_len) != 0 || sshbuf_get_cstring(request, &user, &user_len) != 0 ||
sshbuf_get_cstring(request, &domain, &domain_len) != 0 ||
user_len > MAX_USER_LEN || user_len > MAX_USER_LEN ||
domain_len > MAX_FQDN_LEN ||
sshbuf_get_string_direct(request, &sig, &sig_len) != 0 || sshbuf_get_string_direct(request, &sig, &sig_len) != 0 ||
sshbuf_get_string_direct(request, &blob, &blob_len) != 0 || sshbuf_get_string_direct(request, &blob, &blob_len) != 0 ||
sshkey_from_blob(key_blob, key_blob_len, &key) != 0) { sshkey_from_blob(key_blob, key_blob_len, &key) != 0) {
@ -285,12 +282,13 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
goto done; goto done;
} }
wuser[0] = L'\0'; if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
wdomain[0] = L'\0'; debug("out of memory");
if (MultiByteToWideChar(CP_UTF8, 0, user, user_len + 1, wuser, MAX_USER_LEN) == 0 || goto done;
(domain_len != 0 && MultiByteToWideChar(CP_UTF8, 0, domain, domain_len + 1, wdomain, MAX_FQDN_LEN) == 0) || }
(token = generate_user_token(wuser, wdomain)) == 0) {
debug("unable to generate token for user %ls", wuser); if ((token = generate_user_token(user_utf16)) == 0) {
debug("unable to generate token for user %ls", user_utf16);
goto done; goto done;
} }
@ -302,8 +300,8 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
} }
if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, restricted_token, &wuser_home) != S_OK || if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, restricted_token, &wuser_home) != S_OK ||
pubkey_allowed(key, wuser, wuser_home) != 1) { pubkey_allowed(key, user_utf16, wuser_home) != 1) {
debug("unable to verify public key for user %ls (profile:%ls)", wuser, wuser_home); debug("unable to verify public key for user %ls (profile:%ls)", user_utf16, wuser_home);
goto done; goto done;
} }
@ -322,7 +320,11 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
con->auth_token = restricted_token; con->auth_token = restricted_token;
restricted_token = NULL; restricted_token = NULL;
LoadProfile(con, wuser, wdomain); if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
udom_utf16 = tmp + 1;
*tmp = L'\0';
}
LoadProfile(con, user_utf16, udom_utf16);
r = 0; r = 0;
done: done:
@ -332,6 +334,8 @@ done:
if (user) if (user)
free(user); free(user);
if (user_utf16)
free(user_utf16);
if (key) if (key)
sshkey_free(key); sshkey_free(key);
if (wuser_home) if (wuser_home)

View File

@ -33,6 +33,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#ifdef WINDOWS
#include <lm.h>
#endif
#include "xmalloc.h" #include "xmalloc.h"
#include "groupaccess.h" #include "groupaccess.h"
@ -49,6 +52,82 @@ static char **groups_byname;
int int
ga_init(const char *user, gid_t base) ga_init(const char *user, gid_t base)
{ {
#ifdef WINDOWS
DWORD i = 0, j = 0;
LPLOCALGROUP_USERS_INFO_0 local_groups_info = NULL, tmp_groups_info;
wchar_t *user_utf16 = NULL, *full_name_utf16 = NULL, *udom_utf16 = NULL, *tmp;
char *group_utf8 = NULL;
DWORD entries_read = 0, total_entries = 0, full_name_len = 0, index = 0;
NET_API_STATUS nStatus;
if (ngroups > 0)
ga_free();
user_utf16 = utf8_to_utf16(user);
if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
errno = ENOMEM;
goto done;
}
full_name_len = wcslen(user_utf16) + 1;
if ((full_name_utf16 = malloc(full_name_len * sizeof(wchar_t))) == NULL) {
errno = ENOMEM;
goto done;
}
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
udom_utf16 = tmp + 1;
*tmp = L'\0';
index = wcslen(udom_utf16) + 1;
wmemcpy(full_name_utf16, udom_utf16, index);
full_name_utf16[wcslen(udom_utf16)] = L'\\';
}
wmemcpy(full_name_utf16 + index, user_utf16, wcslen(user_utf16) + 1);
nStatus = NetUserGetLocalGroups(NULL,
full_name_utf16,
0,
LG_INCLUDE_INDIRECT,
(LPBYTE *)&local_groups_info,
MAX_PREFERRED_LENGTH,
&entries_read,
&total_entries);
if (NERR_Success != nStatus) {
error("NetUserGetLocalGroups() failed with error: %u",
nStatus);
errno = ENOENT;
goto done;
}
if (entries_read != total_entries) {
error("NetUserGetLocalGroups(): entries_read (%u) is not equal to "
"total_entries (%u) for user %.100s", entries_read, total_entries, user);
errno = ENOENT;
goto done;
}
if ((tmp_groups_info = local_groups_info) != NULL) {
groups_byname = xcalloc(entries_read, sizeof(*groups_byname));
for (i = 0, j = 0; i < total_entries; i++)
{
if ((group_utf8 = utf16_to_utf8(tmp_groups_info->lgrui0_name)) == NULL) {
errno = ENOMEM;
goto done;
}
groups_byname[j++] = group_utf8;
tmp_groups_info++;
}
}
done:
if(user_utf16 != NULL)
free(user_utf16);
if(full_name_utf16 != NULL)
free(full_name_utf16);
if (local_groups_info != NULL)
NetApiBufferFree(local_groups_info);
#else /* !WINDOWS */
gid_t *groups_bygid; gid_t *groups_bygid;
int i, j; int i, j;
struct group *gr; struct group *gr;
@ -70,7 +149,9 @@ ga_init(const char *user, gid_t base)
if ((gr = getgrgid(groups_bygid[i])) != NULL) if ((gr = getgrgid(groups_bygid[i])) != NULL)
groups_byname[j++] = xstrdup(gr->gr_name); groups_byname[j++] = xstrdup(gr->gr_name);
free(groups_bygid); free(groups_bygid);
#endif /* !WINDOWS */
return (ngroups = j); return (ngroups = j);
} }
/* /*

5
misc.c
View File

@ -226,11 +226,6 @@ pwcopy(struct passwd *pw)
copy->pw_dir = xstrdup(pw->pw_dir); copy->pw_dir = xstrdup(pw->pw_dir);
copy->pw_shell = xstrdup(pw->pw_shell); copy->pw_shell = xstrdup(pw->pw_shell);
#ifdef WINDOWS #ifdef WINDOWS
/* copy additionaly pw entries for Windows */
if (pw->pw_domain != NULL)
copy->pw_domain = xstrdup(pw->pw_domain);
else
copy->pw_domain = NULL;
copy->pw_sid = xstrdup(pw->pw_sid); copy->pw_sid = xstrdup(pw->pw_sid);
#endif /* WINDOWS */ #endif /* WINDOWS */

View File

@ -75,9 +75,11 @@ Class Machine
[string] $localAdminUserName = "localadmin" [string] $localAdminUserName = "localadmin"
[string] $localAdminPassword = "Bull_dog1" [string] $localAdminPassword = "Bull_dog1"
[string] $localAdminAuthorizedKeyPath [string] $localAdminAuthorizedKeyPath
[string] $sshdConfigFile = (join-path $PSScriptRoot "sshd_config")
[string] $backupFileName = (join-path $PSScriptRoot "sshd_backup")
[System.Security.SecureString] $password [System.Security.SecureString] $password
$preLatfpSetting $preLatfpSetting
$localUserprofilePath [string] $localUserprofilePath
#Members on client role #Members on client role
[string []] $clientPrivateKeyPaths [string []] $clientPrivateKeyPaths
@ -177,6 +179,47 @@ Class Machine
} }
} }
[void] SetupSingleSignon([string] $identifyFile) {
.\ssh-add.exe $identifyFile
}
[void] CleanupSingleSignon([string] $identifyFile) {
.\ssh-add.exe -d $identifyFile
}
[void] AddItemInSSHDConfig([string] $key, [string] $value) {
if ( $this.Platform -eq [PlatformType]::Windows ) {
Get-Content $this.sshdConfigFile | % {
if($_.StartsWith($key)) {
"#$_"
}
else {$_}
} | Set-Content $this.sshdConfigFile
Add-Content -Path $this.sshdConfigFile -Value "`r`n$key $value"
Restart-Service sshd
} else {
}
}
[void] BackupSSHDConfig() {
if ( $this.Platform -eq [PlatformType]::Windows ) {
if(Test-path $this.backupFileName) {
Remove-Item -Path $this.backupFileName -Force
}
Copy-Item $this.sshdConfigFile $this.backupFileName -Force
}
}
[void] RestoreSSHDConfig() {
if ( $this.Platform -eq [PlatformType]::Windows ) {
Copy-Item $this.backupFileName $this.sshdConfigFile -Force
Remove-Item -Path $this.backupFileName -Force
Restart-Service sshd
}
}
[void] SetupServerRemoting([Protocol] $protocol) { [void] SetupServerRemoting([Protocol] $protocol) {
if ($this.Platform -eq [PlatformType]::Windows) if ($this.Platform -eq [PlatformType]::Windows)
{ {
@ -240,6 +283,56 @@ Class Machine
} }
} }
[void] AddLocalUser($UserName, $password) {
$a = Get-LocalUser -Name $UserName -ErrorAction Ignore
if ($a -eq $null)
{
$pass = ConvertTo-SecureString -String $this.localAdminPassword -AsPlainText -Force
$a = New-LocalUser -Name $UserName -Password $pass -AccountNeverExpires -PasswordNeverExpires -UserMayNotChangePassword
}
}
[void] AddLocalGroup($groupName) {
$g = Get-LocalGroup -Name $groupName -ErrorAction Ignore
if ($g -eq $null)
{
$g = New-LocalGroup -Name $groupName
}
}
[void] AddUserToLocalGroup($UserName, $password, $groupName) {
if ( $this.Platform -eq [PlatformType]::Windows ) {
$this.AddLocalUser($UserName, $password)
$this.AddLocalGroup($groupName)
if((Get-LocalGroupMember -Name $groupName -Member $UserName -ErrorAction Ignore ) -eq $null)
{
Add-LocalGroupMember -Name $groupName -Member $UserName
}
} else {
#Todo add local user and add it to a user group on linux
}
}
[void] RemoveUserFromLocalGroup($UserName, $groupName) {
if ( $this.Platform -eq [PlatformType]::Windows ) {
if((Get-LocalGroupMember -Name $groupName -Member $UserName -ErrorAction Ignore ) -eq $null)
{
Remove-LocalGroupMember -Name $groupName -Member $UserName
}
} else {
#Todo add local user and add it to a user group on linux
}
}
[void] ClenaupLocalGroup($groupName) {
$g = Get-LocalGroup -Name $groupName -ErrorAction Ignore
if ($g -eq $null)
{
$g | Remove-LocalGroup
}
}
[void] AddAdminUser($UserName, $password) { [void] AddAdminUser($UserName, $password) {
if ( $this.Platform -eq [PlatformType]::Windows ) { if ( $this.Platform -eq [PlatformType]::Windows ) {
$a = Get-LocalUser -Name $UserName -ErrorAction Ignore $a = Get-LocalUser -Name $UserName -ErrorAction Ignore
@ -253,8 +346,7 @@ Class Machine
Add-LocalGroupMember -SID s-1-5-32-544 -Member $a Add-LocalGroupMember -SID s-1-5-32-544 -Member $a
} }
} else { } else {
#Todo add local user and add it to administrators group on linux #Todo add local user and add it to a administrators on linux
#Todo: get $localUserprofilePath
} }
} }

View File

@ -0,0 +1,161 @@
using module .\PlatformAbstractLayer.psm1
Describe "Tests of sshd_config" -Tags "CI" {
BeforeAll {
$fileName = "test.txt"
$filePath = Join-Path ${TestDrive} $fileName
[Machine] $client = [Machine]::new([MachineRole]::Client)
[Machine] $server = [Machine]::new([MachineRole]::Server)
$client.SetupClient($server)
$server.SetupServer($client)
}
AfterAll {
$client.CleanupClient()
$server.CleanupServer()
}
<#
Settings in the sshd_config:
DenyUsers denyuser1 denyu*2 denyuse?3,
AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
DenyGroups denygroup1 denygr*p2 deny?rou?3
AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
#>
Context "Tests of AllowGroups, AllowUsers, DenyUsers, DenyGroups" {
BeforeAll {
Remove-Item -Path $filePath -Force -ea silentlycontinue
$password = "Bull_dog1"
$allowUser1 = "allowuser1"
$allowUser2 = "allowuser2"
$allowUser3 = "allowuser3"
$allowUser4 = "allowuser4"
$denyUser1 = "denyuser1"
$denyUser2 = "denyuser2"
$denyUser3 = "denyuser3"
$localuser1 = "localuser1"
$localuser2 = "localuser2"
$localuser3 = "localuser3"
$allowGroup1 = "allowgroup1"
$allowGroup2 = "allowgroup2"
$allowGroup3 = "allowgroup3"
$denyGroup1 = "denygroup1"
$denyGroup2 = "denygroup2"
$denyGroup3 = "denygroup3"
$client.AddPasswordSetting($password)
}
AfterEach {
Remove-Item -Path $filePath -Force -ea ignore
}
AfterAll {
$client.CleanupPasswordSetting()
}
It 'User with full name in the list of AllowUsers' {
$server.AddUserToLocalGroup($allowUser1, $password, $allowGroup1)
$client.RunCmd(".\ssh $($allowUser1)@$($server.MachineName) hostname > $filePath")
Get-Content $filePath | Should be $server.MachineName
$server.RemoveUserFromLocalGroup($allowUser1, $allowGroup1)
}
It 'User with * wildcard' {
$server.AddUserToLocalGroup($allowUser2, $password, $allowGroup1)
$client.RunCmd(".\ssh $($allowUser2)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Be 0
Get-Content $filePath | Should be $server.MachineName
$server.RemoveUserFromLocalGroup($allowUser2, $allowGroup1)
}
It 'User with ? wildcard' {
$server.AddUserToLocalGroup($allowUser3, $password, $allowGroup1)
$client.RunCmd(".\ssh $($allowUser3)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Be 0
Get-Content $filePath | Should be $server.MachineName
$server.RemoveUserFromLocalGroup($allowUser3, $allowGroup1)
}
It 'User with full name in the list of AllowUsers but not in any AllowGroups' {
$server.AddLocalUser($allowUser4, $password)
$client.RunCmd(".\ssh $($allowUser4)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
}
It 'User with full name in the list of DenyUsers' {
$server.AddUserToLocalGroup($denyUser1, $password, $allowGroup1)
$client.RunCmd(".\ssh $($denyUser1)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($denyUser1, $allowGroup1)
}
It 'User with * wildcard in the list of DenyUsers' {
$server.AddUserToLocalGroup($denyUser2, $password, $allowGroup1)
$str = ".\ssh $($denyUser2)@$($server.MachineName) hostname > $filePath"
$client.RunCmd(".\ssh $($denyUser2)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($denyUser2, $allowGroup1)
}
It 'User with ? wildcard in the list of DenyUsers' {
$server.AddUserToLocalGroup($denyUser3, $password, $allowGroup1)
$client.RunCmd(".\ssh $($denyUser3)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($denyUser3, $allowGroup1)
}
It 'User is listed in the list of AllowUsers but also in a full name DenyGroups and AllowGroups' {
$server.AddUserToLocalGroup($localuser1, $password, $allowGroup1)
$server.AddUserToLocalGroup($localuser1, $password, $denyGroup1)
$client.RunCmd(".\ssh $($localuser1)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($localuser1, $allowGroup1)
$server.RemoveUserFromLocalGroup($localuser1, $denyGroup1)
}
It 'User is listed in the list of AllowUsers but also in a wildcard * DenyGroups' {
$server.AddUserToLocalGroup($localuser2, $password, $denyGroup2)
$client.RunCmd(".\ssh $($localuser2)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($localuser2, $denyGroup2)
}
It 'User is listed in the list of AllowUsers but also in a wildcard ? DenyGroups' {
$server.AddUserToLocalGroup($localuser3, $password, $denyGroup3)
$client.RunCmd(".\ssh $($localuser3)@$($server.MachineName) hostname > $filePath")
$LASTEXITCODE | Should Not Be 0
Get-Content $filePath | Should BeNullOrEmpty
$server.RemoveUserFromLocalGroup($localuser3, $denyGroup3)
}
}
}

View File

@ -0,0 +1,127 @@
# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
# The default requires explicit activation of protocol 1
#Protocol 2
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024
# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
LogLevel DEBUG3
# Authentication:
#LoginGraceTime 2m
#PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
#RSAAuthentication yes
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM no
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#UsePrivilegeSeparation yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10
#PermitTunnel no
#ChrootDirectory none
# no default banner path
#Banner none
# override default of no subsystems
Subsystem sftp sftp-server.exe
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# ForceCommand cvs server
PubkeyAcceptedKeyTypes ssh-ed25519*
DenyUsers denyuser1 deny*2 denyuse?3,
AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
DenyGroups denygroup1 denygr*p2 deny?rou?3
AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*