Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions contrib/win32/openssh/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ Before building OpenSSH for Windows, install the following:
same install / v143 toolset automatically.

2. Git for Windows.
The build script expects git.exe to be on PATH (it will add
"%ProgramFiles%\Git\cmd" to the machine PATH if missing).
The build script expects git.exe to be on PATH.

Comment thread
eransha-salvador marked this conversation as resolved.
3. vcpkg (one-time bootstrap).
Dependencies (LibreSSL, libfido2, zlib, libcbor) are managed via a
Expand Down
19 changes: 19 additions & 0 deletions contrib/win32/openssh/sshd-auth.vcxproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="paths.targets" />
<!-- sshd-auth is a privsep helper spawned by sshd as a different user and has
no desktop/window-station access. user32's DllMain binds to the process
window station and fails with STATUS_DLL_INIT_FAILED in restricted
environments (e.g. WinPE). Two mitigations: (1) add delayimp.lib and
delay-load user32 so its DLL is only loaded when a user32 API is
actually called, and (2) keep user32.lib (needed for the delay-load
thunks). sshd-auth only transitively references ShowWindow /
GetWindowPlacement from console.c's ConRestoreViewRect_NoPtyHack
helper, which sshd-auth does not execute, so in practice user32 is
never loaded. The ItemDefinitionGroup with /DELAYLOAD is placed after
Microsoft.Cpp.props (where the Link item type becomes defined). -->
<PropertyGroup>
<AdditionalDependentLibs>$(AdditionalDependentLibs);delayimp.lib</AdditionalDependentLibs>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
Expand Down Expand Up @@ -112,6 +126,11 @@
<VcpkgEnableManifest>true</VcpkgEnableManifest>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<Link>
<AdditionalOptions>/DELAYLOAD:user32.dll %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
Expand Down
32 changes: 28 additions & 4 deletions contrib/win32/win32compat/win32_usertoken_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,24 @@ EnablePrivilege(const char *privName, int enabled)
return;
}

static BOOL
is_domain_joined_machine(void)
{
BOOL result = FALSE;
LPWSTR name = NULL;
NETSETUP_JOIN_STATUS s = NetSetupUnknownStatus;
DWORD api_res = NetGetJoinInformation(NULL, &name, &s);
if (api_res == NERR_Success) {
result = s == NetSetupDomainName;
NetApiBufferFree(name);
name = NULL;
} else {
debug3("%s: NetGetJoinInformation() failed. Error %d.", __FUNCTION__, api_res);
}
debug3("%s: NetGetJoinInformation(). Join result %d", __FUNCTION__, result);
return result;
}

HANDLE
generate_s4u_user_token(wchar_t* user_cpn, int impersonation) {
HANDLE lsa_handle = NULL, token = NULL;
Expand All @@ -112,7 +130,8 @@ generate_s4u_user_token(wchar_t* user_cpn, int impersonation) {
* so only the only two formats are a NetBiosDomain\SamAccountName which is
* a domain account or just SamAccountName in which is a local account */
BOOL domain_user = wcschr(user_cpn, L'\\') != NULL;

BOOL use_kerberos = domain_user && is_domain_joined_machine();

/* initialize connection to local security provider */
if (impersonation) {

Expand All @@ -132,11 +151,11 @@ generate_s4u_user_token(wchar_t* user_cpn, int impersonation) {
goto done;
}

InitLsaString(&auth_package_name, (domain_user) ? MICROSOFT_KERBEROS_NAME_A : MSV1_0_PACKAGE_NAME);
InitLsaString(&auth_package_name, use_kerberos ? MICROSOFT_KERBEROS_NAME_A : MSV1_0_PACKAGE_NAME);
if (ret = LsaLookupAuthenticationPackage(lsa_handle, &auth_package_name, &auth_package_id) != STATUS_SUCCESS)
goto done;

if (domain_user) {
if (use_kerberos) {

/* lookup the user principal name for the account */
WCHAR domain_upn[MAX_UPN_LEN + 1];
Expand Down Expand Up @@ -168,6 +187,11 @@ generate_s4u_user_token(wchar_t* user_cpn, int impersonation) {
}
else {

/* if a domain prefix slipped through (non-domain-joined host. e.g. winpe is backed with such domain),
point past it without mutating the caller's buffer */
wchar_t *backslash = wcschr(user_cpn, L'\\');
Comment thread
tgauth marked this conversation as resolved.
if (backslash != NULL)
user_cpn = backslash + 1;
MSV1_0_S4U_LOGON *s4u_logon;
logon_info_size = sizeof(MSV1_0_S4U_LOGON);

Expand Down Expand Up @@ -432,7 +456,7 @@ load_user_profile(HANDLE user_token, char* user)
EnablePrivilege("SeBackupPrivilege", 1);
EnablePrivilege("SeRestorePrivilege", 1);
if (LoadUserProfileW(user_token, &profileInfo) == FALSE) {
debug3("%s: LoadUserProfileW() failed for user %S with error %d.", __FUNCTION__, GetLastError());
debug3("%s: LoadUserProfileW() failed for user %S with error %d.", __FUNCTION__, user_name, GetLastError());
}
EnablePrivilege("SeBackupPrivilege", 0);
EnablePrivilege("SeRestorePrivilege", 0);
Expand Down