diff --git a/contrib/win32/openssh/paths.targets b/contrib/win32/openssh/paths.targets
index 46b4e4eaa..f2c034644 100644
--- a/contrib/win32/openssh/paths.targets
+++ b/contrib/win32/openssh/paths.targets
@@ -12,7 +12,7 @@
true
libcrypto.lib;
8.1
- bcrypt.lib;Userenv.lib;Crypt32.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Netapi32.lib;Rpcrt4.lib
+ bcrypt.lib;Userenv.lib;Crypt32.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Netapi32.lib;Rpcrt4.lib;ntdll.lib
false
\ No newline at end of file
diff --git a/contrib/win32/win32compat/lsa_missingdefs.h b/contrib/win32/win32compat/lsa_missingdefs.h
new file mode 100644
index 000000000..838c1b316
--- /dev/null
+++ b/contrib/win32/win32compat/lsa_missingdefs.h
@@ -0,0 +1,60 @@
+/*
+* Missing public definitions from Ntsecapi.h
+*/
+
+
+typedef enum _LSA_SID_NAME_MAPPING_OPERATION_TYPE {
+ LsaSidNameMappingOperation_Add,
+ LsaSidNameMappingOperation_Remove,
+ LsaSidNameMappingOperation_AddMultiple,
+} LSA_SID_NAME_MAPPING_OPERATION_TYPE, *PLSA_SID_NAME_MAPPING_OPERATION_TYPE;
+
+typedef enum _LSA_SID_NAME_MAPPING_OPERATION_ERROR {
+ LsaSidNameMappingOperation_Success,
+ LsaSidNameMappingOperation_NonMappingError,
+ LsaSidNameMappingOperation_NameCollision,
+ LsaSidNameMappingOperation_SidCollision,
+ LsaSidNameMappingOperation_DomainNotFound,
+ LsaSidNameMappingOperation_DomainSidPrefixMismatch,
+ LsaSidNameMappingOperation_MappingNotFound,
+} LSA_SID_NAME_MAPPING_OPERATION_ERROR, *PLSA_SID_NAME_MAPPING_OPERATION_ERROR;
+
+typedef struct _LSA_SID_NAME_MAPPING_OPERATION_ADD_INPUT {
+ UNICODE_STRING DomainName;
+ UNICODE_STRING AccountName;
+ PSID Sid;
+ ULONG Flags;
+} LSA_SID_NAME_MAPPING_OPERATION_ADD_INPUT, *PLSA_SID_NAME_MAPPING_OPERATION_ADD_INPUT;
+
+typedef struct _LSA_SID_NAME_MAPPING_OPERATION_REMOVE_INPUT {
+ UNICODE_STRING DomainName;
+ UNICODE_STRING AccountName;
+} LSA_SID_NAME_MAPPING_OPERATION_REMOVE_INPUT, *PLSA_SID_NAME_MAPPING_OPERATION_REMOVE_INPUT;
+
+typedef union _LSA_SID_NAME_MAPPING_OPERATION_INPUT {
+ LSA_SID_NAME_MAPPING_OPERATION_ADD_INPUT AddInput;
+ LSA_SID_NAME_MAPPING_OPERATION_REMOVE_INPUT RemoveInput;
+} LSA_SID_NAME_MAPPING_OPERATION_INPUT, *PLSA_SID_NAME_MAPPING_OPERATION_INPUT;
+
+typedef struct _LSA_SID_NAME_MAPPING_OPERATION_GENERIC_OUTPUT {
+ LSA_SID_NAME_MAPPING_OPERATION_ERROR ErrorCode;
+} LSA_SID_NAME_MAPPING_OPERATION_GENERIC_OUTPUT, *PLSA_SID_NAME_MAPPING_OPERATION_GENERIC_OUTPUT;
+
+typedef LSA_SID_NAME_MAPPING_OPERATION_GENERIC_OUTPUT LSA_SID_NAME_MAPPING_OPERATION_ADD_OUTPUT, *PLSA_SID_NAME_MAPPING_OPERATION_ADD_OUTPUT;
+typedef LSA_SID_NAME_MAPPING_OPERATION_GENERIC_OUTPUT LSA_SID_NAME_MAPPING_OPERATION_REMOVE_OUTPUT, *PLSA_SID_NAME_MAPPING_OPERATION_REMOVE_OUTPUT;
+
+typedef union _LSA_SID_NAME_MAPPING_OPERATION_OUTPUT {
+ LSA_SID_NAME_MAPPING_OPERATION_ADD_OUTPUT AddOutput;
+ LSA_SID_NAME_MAPPING_OPERATION_REMOVE_OUTPUT RemoveOutput;
+} LSA_SID_NAME_MAPPING_OPERATION_OUTPUT, *PLSA_SID_NAME_MAPPING_OPERATION_OUTPUT;
+
+NTSTATUS WINAPI LsaManageSidNameMapping(
+ LSA_SID_NAME_MAPPING_OPERATION_TYPE OpType,
+ PLSA_SID_NAME_MAPPING_OPERATION_INPUT OpInput,
+ PLSA_SID_NAME_MAPPING_OPERATION_OUTPUT *OpOutput
+);
+
+VOID WINAPI RtlInitUnicodeString(
+ PUNICODE_STRING DestinationString,
+ PCWSTR SourceString
+);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/win32_usertoken_utils.c b/contrib/win32/win32compat/win32_usertoken_utils.c
index 3f0350ca5..e455088f3 100644
--- a/contrib/win32/win32compat/win32_usertoken_utils.c
+++ b/contrib/win32/win32compat/win32_usertoken_utils.c
@@ -40,8 +40,11 @@
#include "inc\utf.h"
#include "logonuser.h"
#include
+#include
+#include
#include
#include "misc_internal.h"
+#include "lsa_missingdefs.h"
#include "Debug.h"
#pragma warning(push, 3)
@@ -118,7 +121,7 @@ done:
#define MAX_PW_LEN 64
static HANDLE
-generate_user_token(wchar_t* user_cpn) {
+generate_s4u_user_token(wchar_t* user_cpn) {
HANDLE lsa_handle = 0, token = 0;
LSA_OPERATIONAL_MODE mode;
ULONG auth_package_id;
@@ -329,6 +332,8 @@ done:
return token;
}
+HANDLE generate_sshd_virtual_token();
+
HANDLE
get_user_token(char* user) {
HANDLE token = NULL;
@@ -339,12 +344,18 @@ get_user_token(char* user) {
goto done;
}
- if ((token = generate_user_token(user_utf16)) == 0) {
+ if (wcscmp(user_utf16, L"sshd") == 0) {
+ if ((token = generate_sshd_virtual_token()) != 0)
+ goto done;
+ debug3("unable to generate sshd virtual token, falling back to s4u");
+ }
+
+ if ((token = generate_s4u_user_token(user_utf16)) == 0) {
error("unable to generate token for user %ls", user_utf16);
/* work around for https://github.com/PowerShell/Win32-OpenSSH/issues/727 by doing a fake login */
LogonUserExExWHelper(L"FakeUser", L"FakeDomain", L"FakePasswd",
LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, NULL, &token, NULL, NULL, NULL, NULL);
- if ((token = generate_user_token(user_utf16)) == 0) {
+ if ((token = generate_s4u_user_token(user_utf16)) == 0) {
error("unable to generate token on 2nd attempt for user %ls", user_utf16);
goto done;
}
@@ -382,4 +393,199 @@ done:
return r;
}
+
+/* *** virtual account token generation logic ***/
+
+char* LSAMappingErrorDetails[] = {
+ "LsaSidNameMappingOperation_Success",
+ "LsaSidNameMappingOperation_NonMappingError",
+ "LsaSidNameMappingOperation_NameCollision",
+ "LsaSidNameMappingOperation_SidCollision",
+ "LsaSidNameMappingOperation_DomainNotFound",
+ "LsaSidNameMappingOperation_DomainSidPrefixMismatch",
+ "LsaSidNameMappingOperation_MappingNotFound"
+};
+
+#define VIRTUALUSER_DOMAIN L"VIRTUAL USERS"
+#define VIRTUALUSER_GROUP_NAME L"ALL VIRTUAL USERS"
+
+/* returns 0 on success -1 on failure */
+int
+AddSidMappingToLsa(PUNICODE_STRING domain_name,
+ PUNICODE_STRING account_name,
+ PSID sid)
+{
+ LSA_SID_NAME_MAPPING_OPERATION_INPUT input = { 0 };
+ PLSA_SID_NAME_MAPPING_OPERATION_OUTPUT p_output = NULL;
+ LSA_SID_NAME_MAPPING_OPERATION_ERROR op_result =
+ LsaSidNameMappingOperation_NonMappingError;
+ NTSTATUS status = STATUS_SUCCESS;
+ int ret = 0;
+
+ input.AddInput.DomainName = *domain_name;
+ if (account_name)
+ input.AddInput.AccountName = *account_name;
+ input.AddInput.Sid = sid;
+
+ status = LsaManageSidNameMapping(LsaSidNameMappingOperation_Add,
+ &input,
+ &p_output);
+ if (status != STATUS_SUCCESS) {
+ ret = -1;
+ if (p_output) {
+ op_result = p_output->AddOutput.ErrorCode;
+ if (op_result == LsaSidNameMappingOperation_NameCollision || op_result == LsaSidNameMappingOperation_SidCollision)
+ ret = 0; /* OK as it failed due to collision */
+ else
+ error("LsaManageSidNameMapping failed with : %s \n", LSAMappingErrorDetails[op_result]);
+ }
+ else
+ error("LsaManageSidNameMapping failed with ntstatus: %d \n", status);
+ }
+
+ if (p_output)
+ LsaFreeMemory(p_output);
+
+ return ret;
+}
+
+
+int RemoveVirtualAccountLSAMapping(PUNICODE_STRING domain_name,
+ PUNICODE_STRING account_name)
+{
+ int ret = 0;
+
+ LSA_SID_NAME_MAPPING_OPERATION_INPUT input = { 0 };
+ PLSA_SID_NAME_MAPPING_OPERATION_OUTPUT p_output = NULL;
+ PLSA_SID_NAME_MAPPING_OPERATION_REMOVE_INPUT remove_input = &input.RemoveInput;
+
+ remove_input->DomainName = *domain_name;
+ if (account_name)
+ remove_input->AccountName = *account_name;
+
+ NTSTATUS status = LsaManageSidNameMapping(LsaSidNameMappingOperation_Remove,
+ &input,
+ &p_output);
+ if (status != STATUS_SUCCESS)
+ ret = -1;
+
+ if (p_output)
+ LsaFreeMemory(p_output);
+
+ return ret;
+}
+
+HANDLE generate_sshd_virtual_token()
+{
+ SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY;
+ UNICODE_STRING domain, group, account;
+ WCHAR va_name[32]; /* enough to accomodate sshd_123457890 */
+
+ PSID sid_domain = NULL, sid_group = NULL, sid_user = NULL;
+ HANDLE va_token = 0, va_token_restricted = 0;
+
+ StringCchPrintfW(va_name, 32, L"%s_%d", L"sshd", GetCurrentProcessId());
+
+ RtlInitUnicodeString(&domain, VIRTUALUSER_DOMAIN);
+ RtlInitUnicodeString(&group, VIRTUALUSER_GROUP_NAME);
+ RtlInitUnicodeString(&account, va_name);
+
+ /* Initialize SIDs */
+ /* domain SID - S-1-5-111 */
+ if (!(AllocateAndInitializeSid(&nt_authority,
+ 1,
+ 111,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ &sid_domain)))
+ goto cleanup;
+
+ /* group SID - S-1-5-111-0 */
+ if (!(AllocateAndInitializeSid(&nt_authority,
+ 2,
+ 111,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ &sid_group)))
+ goto cleanup;
+
+ /*
+ * account SID
+ * this is derived from higher RIDs in sshd service account SID to ensure there are no conflicts
+ * S-1-5-80-3847866527-469524349-687026318-516638107-1125189541 (Well Known group: NT SERVICE\sshd)
+ * Ex account SID - S-1-5-111-3847866527-469524349-687026318-516638107-1125189541-123
+ */
+ if (!(AllocateAndInitializeSid(&nt_authority,
+ 7,
+ 111,
+ 3847866527,
+ 469524349,
+ 687026318,
+ 516638107,
+ 1125189541,
+ GetCurrentProcessId(),
+ 0,
+ &sid_user)))
+ goto cleanup;
+
+ /* Map the domain SID */
+ if (AddSidMappingToLsa(&domain, NULL, sid_domain) != 0)
+ goto cleanup;
+
+ /* Map the group SID */
+ if (AddSidMappingToLsa(&domain, &group, sid_group) != 0)
+ goto cleanup;
+
+ /* Map the user SID */
+ if (AddSidMappingToLsa(&domain, &account, sid_user) != 0)
+ goto cleanup;
+
+ /* Logon virtual and create token */
+ if (!LogonUserExExWHelper(
+ va_name,
+ VIRTUALUSER_DOMAIN,
+ L"",
+ LOGON32_LOGON_INTERACTIVE,
+ LOGON32_PROVIDER_VIRTUAL,
+ NULL,
+ &va_token,
+ NULL,
+ NULL,
+ NULL,
+ NULL)) {
+ debug3("LogonUserExExW failed with %d \n", GetLastError());
+ goto cleanup;
+ }
+
+ /* remove all privileges */
+ if (!CreateRestrictedToken(va_token, DISABLE_MAX_PRIVILEGE, 0, NULL, 0, NULL, 0, NULL, &va_token_restricted ))
+ debug3("CreateRestrictedToken failed with %d \n", GetLastError());
+
+ CloseHandle(va_token);
+
+cleanup:
+ RemoveVirtualAccountLSAMapping(&domain, &account);
+
+ if (sid_domain)
+ FreeSid(sid_domain);
+ if (sid_user)
+ FreeSid(sid_user);
+ if (sid_group)
+ FreeSid(sid_group);
+
+ return va_token_restricted;
+}
+
+
+
#pragma warning(pop)
\ No newline at end of file
diff --git a/contrib/win32/win32compat/wmain_sshd.c b/contrib/win32/win32compat/wmain_sshd.c
index b90d7120f..1072839c8 100644
--- a/contrib/win32/win32compat/wmain_sshd.c
+++ b/contrib/win32/win32compat/wmain_sshd.c
@@ -129,7 +129,7 @@ generate_host_keys()
ui.usri1_priv = USER_PRIV_USER;
ui.usri1_home_dir = NULL;
ui.usri1_comment = NULL;
- ui.usri1_flags = UF_SCRIPT;
+ ui.usri1_flags = UF_SCRIPT | UF_DONT_EXPIRE_PASSWD;
ui.usri1_script_path = NULL;
NetUserAdd(NULL, 1, (LPBYTE)&ui, &dwError);