fix lsa auth provider and minor bug fixes (#270)

https://github.com/PowerShell/Win32-OpenSSH/issues/1046
This commit is contained in:
bagajjal 2018-02-02 15:45:32 -08:00 committed by Manoj Ampalam
parent 02d07309e2
commit b10f2232e5
10 changed files with 99 additions and 55 deletions

View File

@ -231,7 +231,7 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
#elif defined(WINDOWS) #elif defined(WINDOWS)
HANDLE password_auth_token = NULL; HANDLE password_auth_token = NULL;
HANDLE process_custom_lsa_auth(char*, const char*, char*); HANDLE process_custom_lsa_auth(const char*, const char*, const char*);
void void
sys_auth_passwd_lsa(Authctxt *authctxt, const char *password) sys_auth_passwd_lsa(Authctxt *authctxt, const char *password)
@ -253,8 +253,7 @@ sys_auth_passwd_lsa(Authctxt *authctxt, const char *password)
lsa_auth_pkg = utf16_to_utf8(lsa_auth_pkg_w); lsa_auth_pkg = utf16_to_utf8(lsa_auth_pkg_w);
if (!lsa_auth_pkg) if (!lsa_auth_pkg)
fatal("utf16_to_utf8 failed to convert lsa_auth_pkg_w:%ls", lsa_auth_pkg_w); fatal("utf16_to_utf8 failed to convert lsa_auth_pkg_w:%ls", lsa_auth_pkg_w);
debug("Authenticating using LSA Auth Package:%ls", lsa_auth_pkg_w);
password_auth_token = process_custom_lsa_auth(authctxt->pw->pw_name, password, lsa_auth_pkg); password_auth_token = process_custom_lsa_auth(authctxt->pw->pw_name, password, lsa_auth_pkg);
} }
} }

2
auth.c
View File

@ -430,7 +430,7 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
#ifdef WINDOWS #ifdef WINDOWS
/* Return if the path is absolute. If not, prepend the '%h\\' */ /* Return if the path is absolute. If not, prepend the '%h\\' */
if ((strlen(file) > 1) && (file[1] == ':')) if(is_absolute_path(file))
return (file); return (file);
i = snprintf(ret, sizeof(ret), "%s\\%s", pw->pw_dir, file); i = snprintf(ret, sizeof(ret), "%s\\%s", pw->pw_dir, file);

View File

@ -1460,7 +1460,7 @@ int
is_absolute_path(char *path) is_absolute_path(char *path)
{ {
int retVal = 0; int retVal = 0;
if (*path == '/' || *path == '\\' || (*path != '\0' && path[1] == ':') || if (*path == '/' || *path == '\\' || (*path != '\0' && isalpha(*path) && path[1] == ':') ||
((strlen(path) >= strlen(PROGRAM_DATA)) && (memcmp(path, PROGRAM_DATA, strlen(PROGRAM_DATA)) == 0))) ((strlen(path) >= strlen(PROGRAM_DATA)) && (memcmp(path, PROGRAM_DATA, strlen(PROGRAM_DATA)) == 0)))
retVal = 1; retVal = 1;

View File

@ -2,7 +2,7 @@
#include <VersionHelpers.h> #include <VersionHelpers.h>
#define PATH_MAX MAX_PATH #define PATH_MAX MAX_PATH
#define SSH_REGISTRY_ROOT L"SOFTWARE\\OpenSSH"
#define GOTO_CLEANUP_IF(_cond_,_err_) do { \ #define GOTO_CLEANUP_IF(_cond_,_err_) do { \
if ((_cond_)) { \ if ((_cond_)) { \
hr = _err_; \ hr = _err_; \

View File

@ -1,11 +1,11 @@
#include <Windows.h> #include <Windows.h>
#include <stdio.h> #include <stdio.h>
#include "Debug.h" #include "Debug.h"
#include "misc_internal.h"
#define MAX_MESSAGE_SIZE 256 * 1024 #define MAX_MESSAGE_SIZE 256 * 1024
#define SSH_ROOT L"SOFTWARE\\OpenSSH" #define SSH_AGENT_ROOT SSH_REGISTRY_ROOT L"\\Agent"
#define SSH_AGENT_ROOT SSH_ROOT L"\\Agent"
#define SSH_KEYS_KEY L"Keys" #define SSH_KEYS_KEY L"Keys"
#define SSH_KEYS_ROOT SSH_AGENT_ROOT L"\\" SSH_KEYS_KEY #define SSH_KEYS_ROOT SSH_AGENT_ROOT L"\\" SSH_KEYS_KEY

View File

@ -1040,6 +1040,7 @@ spawn_child_internal(char* cmd, char *const argv[], HANDLE in, HANDLE out, HANDL
} }
else { else {
errno = GetLastError(); errno = GetLastError();
error("%s failed error:%d", (as_user?"CreateProcessAsUserW":"CreateProcessW"), GetLastError());
goto cleanup; goto cleanup;
} }

View File

@ -35,6 +35,8 @@
#include <Ntsecapi.h> #include <Ntsecapi.h>
#include <ntstatus.h> #include <ntstatus.h>
#include <Shlobj.h> #include <Shlobj.h>
#include <LM.h>
#include "inc\utf.h" #include "inc\utf.h"
#include "logonuser.h" #include "logonuser.h"
#include <Ntsecapi.h> #include <Ntsecapi.h>
@ -223,14 +225,14 @@ done:
} }
HANDLE HANDLE
process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg) process_custom_lsa_auth(const char* user, const char* pwd, const char* lsa_pkg)
{ {
wchar_t *userw = NULL, *pwdw = NULL, *domw = NULL, *tmp, *providerw = NULL; wchar_t *providerw = NULL;
HANDLE token = NULL, lsa_handle = NULL; HANDLE token = NULL, lsa_handle = NULL;
LSA_OPERATIONAL_MODE mode; LSA_OPERATIONAL_MODE mode;
ULONG auth_package_id, logon_info_size = 0; ULONG auth_package_id, logon_info_size = 0;
NTSTATUS ret, subStatus; NTSTATUS ret, subStatus;
wchar_t *logon_info = NULL; wchar_t *logon_info_w = NULL;
LSA_STRING logon_process_name, lsa_auth_package_name, originName; LSA_STRING logon_process_name, lsa_auth_package_name, originName;
TOKEN_SOURCE sourceContext; TOKEN_SOURCE sourceContext;
PVOID pProfile = NULL; PVOID pProfile = NULL;
@ -238,19 +240,34 @@ process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg)
QUOTA_LIMITS quotas; QUOTA_LIMITS quotas;
DWORD cbProfile; DWORD cbProfile;
int retVal = -1; int retVal = -1;
char *domain = NULL, *logon_info = NULL, user_name[UNLEN] = { 0, }, *tmp = NULL;
debug("LSA auth request, user:%s lsa_pkg:%s ", user, lsa_pkg); debug3("LSA auth request, user:%s lsa_pkg:%s ", user, lsa_pkg);
if ((userw = utf8_to_utf16(user)) == NULL || logon_info_size = (ULONG)(strlen(user) + strlen(pwd) + 2); // 1 - ";", 1 - "\0"
(pwdw = utf8_to_utf16(pwd)) == NULL) { strcpy_s(user_name, _countof(user_name), user);
debug("out of memory"); if (tmp = strstr(user_name, "@")) {
goto done; domain = tmp + 1;
*tmp = '\0';
logon_info_size++; // 1 - ";"
} }
/* split user and domain */ logon_info = malloc(logon_info_size);
if ((tmp = wcschr(userw, L'@')) != NULL) { if(!logon_info)
domw = tmp + 1; fatal("%s out of memory", __func__);
*tmp = L'\0';
strcpy_s(logon_info, logon_info_size, user_name);
strcat_s(logon_info, logon_info_size, ";");
strcat_s(logon_info, logon_info_size, pwd);
if (domain) {
strcat_s(logon_info, logon_info_size, ";");
strcat_s(logon_info, logon_info_size, domain);
}
if (NULL == (logon_info_w = utf8_to_utf16(logon_info))) {
error("utf8_to_utf16 failed to convert %s", logon_info);
goto done;
} }
/* call into LSA provider , get and duplicate token */ /* call into LSA provider , get and duplicate token */
@ -268,30 +285,19 @@ process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg)
goto done; goto done;
} }
logon_info_size = (ULONG)((wcslen(userw) + wcslen(pwdw) + wcslen(domw) + 3) * sizeof(wchar_t));
logon_info = (wchar_t *)malloc(logon_info_size);
if (NULL == logon_info)
fatal("%s:out of memory", __func__);
wcscpy_s(logon_info, logon_info_size, userw);
wcscat_s(logon_info, logon_info_size, L";");
wcscat_s(logon_info, logon_info_size, pwdw);
wcscat_s(logon_info, logon_info_size, L";");
wcscat_s(logon_info, logon_info_size, domw);
memcpy(sourceContext.SourceName, "sshd", sizeof(sourceContext.SourceName)); memcpy(sourceContext.SourceName, "sshd", sizeof(sourceContext.SourceName));
if (!AllocateLocallyUniqueId(&sourceContext.SourceIdentifier)) { if (!AllocateLocallyUniqueId(&sourceContext.SourceIdentifier)) {
error("AllocateLocallyUniqueId failed, error:%d", GetLastError()); error("AllocateLocallyUniqueId failed, error:%d", GetLastError());
goto done; goto done;
} }
if ((ret = LsaLogonUser(lsa_handle, if ((ret = LsaLogonUser(lsa_handle,
&originName, &originName,
Network, Network,
auth_package_id, auth_package_id,
logon_info, logon_info_w,
logon_info_size, logon_info_size * sizeof(wchar_t),
NULL, NULL,
&sourceContext, &sourceContext,
&pProfile, &pProfile,
@ -299,8 +305,8 @@ process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg)
&logonId, &logonId,
&token, &token,
&quotas, &quotas,
&subStatus)) != STATUS_SUCCESS) { &subStatus)) != STATUS_SUCCESS) {
if(ret == STATUS_ACCOUNT_RESTRICTION) if (ret == STATUS_ACCOUNT_RESTRICTION)
error("LsaLogonUser failed, error:%x subStatus:%ld", ret, subStatus); error("LsaLogonUser failed, error:%x subStatus:%ld", ret, subStatus);
else else
error("LsaLogonUser failed error:%x", ret); error("LsaLogonUser failed error:%x", ret);
@ -308,19 +314,17 @@ process_custom_lsa_auth(char* user, const char* pwd, char* lsa_pkg)
goto done; goto done;
} }
debug3("LSA auth request is successful for user:%s ", user);
retVal = 0; retVal = 0;
done: done:
/* delete allocated memory*/
if (lsa_handle) if (lsa_handle)
LsaDeregisterLogonProcess(lsa_handle); LsaDeregisterLogonProcess(lsa_handle);
if (logon_info)
free(logon_info);
if (pProfile) if (pProfile)
LsaFreeReturnBuffer(pProfile); LsaFreeReturnBuffer(pProfile);
if (userw) if (logon_info)
free(userw); free(logon_info);
if (pwdw) if (logon_info_w)
free(pwdw); free(logon_info_w);
return token; return token;
} }

View File

@ -35,6 +35,8 @@
#include <Windows.h> #include <Windows.h>
#include <wchar.h> #include <wchar.h>
#include <Lm.h> #include <Lm.h>
#include <sddl.h>
#include "inc\utf.h" #include "inc\utf.h"
#include "misc_internal.h" #include "misc_internal.h"
@ -163,15 +165,19 @@ create_prgdata_ssh_folder()
char ssh_cfg_dir[PATH_MAX] = { 0, }; char ssh_cfg_dir[PATH_MAX] = { 0, };
strcpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), get_program_data_path()); strcpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), get_program_data_path());
strcat_s(ssh_cfg_dir, _countof(ssh_cfg_dir), "\\ssh"); strcat_s(ssh_cfg_dir, _countof(ssh_cfg_dir), "\\ssh");
if (create_directory_withsddl(ssh_cfg_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)") < 0) if (create_directory_withsddl(ssh_cfg_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)") < 0) {
fatal("failed to create %s", ssh_cfg_dir); printf("failed to create %s", ssh_cfg_dir);
exit(255);
}
/* create logs folder */ /* create logs folder */
char logs_dir[PATH_MAX] = { 0, }; char logs_dir[PATH_MAX] = { 0, };
strcat_s(logs_dir, _countof(logs_dir), ssh_cfg_dir); strcat_s(logs_dir, _countof(logs_dir), ssh_cfg_dir);
strcat_s(logs_dir, _countof(logs_dir), "\\logs"); strcat_s(logs_dir, _countof(logs_dir), "\\logs");
if (create_directory_withsddl(logs_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)") < 0) if (create_directory_withsddl(logs_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)") < 0) {
fatal("failed to create %s", logs_dir); printf("failed to create %s", logs_dir);
exit(255);
}
/* COPY sshd_config_default to %programData%\openssh\sshd_config */ /* COPY sshd_config_default to %programData%\openssh\sshd_config */
char sshd_config_path[PATH_MAX] = { 0, }; char sshd_config_path[PATH_MAX] = { 0, };
@ -183,16 +189,47 @@ create_prgdata_ssh_folder()
strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), w32_programdir()); strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), w32_programdir());
strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), "\\sshd_config_default"); strcat_s(sshd_config_default_path, _countof(sshd_config_default_path), "\\sshd_config_default");
if (copy_file(sshd_config_default_path, sshd_config_path) < 0) if (copy_file(sshd_config_default_path, sshd_config_path) < 0) {
fatal("Failed to copy %s to %s, error:%d", sshd_config_default_path, sshd_config_path, GetLastError()); printf("Failed to copy %s to %s, error:%d", sshd_config_default_path, sshd_config_path, GetLastError());
exit(255);
}
} }
} }
/* Create HKLM\Software\OpenSSH windows registry key */
static void
create_openssh_registry_key()
{
HKEY ssh_registry_root = NULL;
wchar_t* sddl_str;
SECURITY_ATTRIBUTES sa;
int r;
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(sa);
/*
* SDDL - FullAcess to System and Builtin/Admins and restricted access to Authenticated users
* 0x12019b - FILE_GENERIC_READ/WRITE minus FILE_CREATE_PIPE_INSTANCE
*/
sddl_str = L"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;0x12019b;;;AU)";
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl_str, SDDL_REVISION_1, &sa.lpSecurityDescriptor, &sa.nLength)) {
printf("cannot convert sddl ERROR:%d", GetLastError());
return;
}
if ((r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, SSH_REGISTRY_ROOT, 0, 0, 0, KEY_WRITE, &sa, &ssh_registry_root, 0)) == ERROR_SUCCESS)
RegCloseKey(ssh_registry_root);
else
printf("cannot create ssh root reg key, ERROR:%d", r);
}
static void static void
prereq_setup() prereq_setup()
{ {
create_prgdata_ssh_folder(); create_prgdata_ssh_folder();
generate_host_keys(); generate_host_keys();
create_openssh_registry_key();
} }
int sshd_main(int argc, wchar_t **wargv) { int sshd_main(int argc, wchar_t **wargv) {
@ -201,8 +238,11 @@ int sshd_main(int argc, wchar_t **wargv) {
_set_invalid_parameter_handler(invalid_parameter_handler); _set_invalid_parameter_handler(invalid_parameter_handler);
if (argc) { if (argc) {
if ((argv = malloc(argc * sizeof(char*))) == NULL) if ((argv = malloc(argc * sizeof(char*))) == NULL) {
fatal("out of memory"); printf("out of memory");
exit(255);
}
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
argv[i] = utf16_to_utf8(wargv[i]); argv[i] = utf16_to_utf8(wargv[i]);
} }

2
sftp.c
View File

@ -397,7 +397,7 @@ make_absolute(char *p, const char *pwd)
* Need to follow up with community if this makes sense in common code * Need to follow up with community if this makes sense in common code
*/ */
char *s1, *s2; char *s1, *s2;
if (p && p[0] != '/' && (p[0] == '\0' || p[1] != ':')) { if (!is_absolute_path(p)) {
abs_str = path_append(pwd, p); abs_str = path_append(pwd, p);
free(p); free(p);
p = abs_str; p = abs_str;

6
sshd.c
View File

@ -774,7 +774,7 @@ privsep_preauth(Authctxt *authctxt)
else { else {
char** argv = privsep_child_cmdline(0); char** argv = privsep_child_cmdline(0);
if (__posix_spawn_asuser(&pid, argv[0], &actions, NULL, argv, NULL, SSH_PRIVSEP_USER) != 0) if (__posix_spawn_asuser(&pid, argv[0], &actions, NULL, argv, NULL, SSH_PRIVSEP_USER) != 0)
error("posix_spawn failed"); error("%s, posix_spawn failed", __func__);
posix_spawn_file_actions_destroy(&actions); posix_spawn_file_actions_destroy(&actions);
} }
close(pmonitor->m_recvfd); close(pmonitor->m_recvfd);
@ -880,7 +880,7 @@ privsep_postauth(Authctxt *authctxt)
else { else {
char** argv = privsep_child_cmdline(1); char** argv = privsep_child_cmdline(1);
if (__posix_spawn_asuser(&pmonitor->m_pid, argv[0], &actions, NULL, argv, NULL, authctxt->pw->pw_name) != 0) if (__posix_spawn_asuser(&pmonitor->m_pid, argv[0], &actions, NULL, argv, NULL, authctxt->pw->pw_name) != 0)
error("posix_spawn failed"); error("%s, posix_spawn failed", __func__);
posix_spawn_file_actions_destroy(&actions); posix_spawn_file_actions_destroy(&actions);
} }
@ -1545,7 +1545,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
error("posix_spawn initialization failed"); error("posix_spawn initialization failed");
else { else {
if (posix_spawn(&pid, rexec_argv[0], &actions, &attributes, rexec_argv, NULL) != 0) if (posix_spawn(&pid, rexec_argv[0], &actions, &attributes, rexec_argv, NULL) != 0)
error("posix_spawn failed"); error("%s, posix_spawn failed", __func__);
posix_spawn_file_actions_destroy(&actions); posix_spawn_file_actions_destroy(&actions);
posix_spawnattr_destroy(&attributes); posix_spawnattr_destroy(&attributes);
} }