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)
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
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);
if (!lsa_auth_pkg)
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);
}
}

2
auth.c
View File

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

View File

@ -1460,7 +1460,7 @@ int
is_absolute_path(char *path)
{
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)))
retVal = 1;

View File

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

View File

@ -1,11 +1,11 @@
#include <Windows.h>
#include <stdio.h>
#include "Debug.h"
#include "misc_internal.h"
#define MAX_MESSAGE_SIZE 256 * 1024
#define SSH_ROOT L"SOFTWARE\\OpenSSH"
#define SSH_AGENT_ROOT SSH_ROOT L"\\Agent"
#define SSH_AGENT_ROOT SSH_REGISTRY_ROOT L"\\Agent"
#define SSH_KEYS_KEY L"Keys"
#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 {
errno = GetLastError();
error("%s failed error:%d", (as_user?"CreateProcessAsUserW":"CreateProcessW"), GetLastError());
goto cleanup;
}

View File

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

View File

@ -35,6 +35,8 @@
#include <Windows.h>
#include <wchar.h>
#include <Lm.h>
#include <sddl.h>
#include "inc\utf.h"
#include "misc_internal.h"
@ -163,15 +165,19 @@ create_prgdata_ssh_folder()
char ssh_cfg_dir[PATH_MAX] = { 0, };
strcpy_s(ssh_cfg_dir, _countof(ssh_cfg_dir), get_program_data_path());
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)
fatal("failed to create %s", ssh_cfg_dir);
if (create_directory_withsddl(ssh_cfg_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;AU)") < 0) {
printf("failed to create %s", ssh_cfg_dir);
exit(255);
}
/* create logs folder */
char logs_dir[PATH_MAX] = { 0, };
strcat_s(logs_dir, _countof(logs_dir), ssh_cfg_dir);
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)
fatal("failed to create %s", logs_dir);
if (create_directory_withsddl(logs_dir, "O:BAD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)") < 0) {
printf("failed to create %s", logs_dir);
exit(255);
}
/* COPY sshd_config_default to %programData%\openssh\sshd_config */
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), "\\sshd_config_default");
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());
if (copy_file(sshd_config_default_path, sshd_config_path) < 0) {
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
prereq_setup()
{
create_prgdata_ssh_folder();
generate_host_keys();
create_openssh_registry_key();
}
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);
if (argc) {
if ((argv = malloc(argc * sizeof(char*))) == NULL)
fatal("out of memory");
if ((argv = malloc(argc * sizeof(char*))) == NULL) {
printf("out of memory");
exit(255);
}
for (i = 0; i < argc; 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
*/
char *s1, *s2;
if (p && p[0] != '/' && (p[0] == '\0' || p[1] != ':')) {
if (!is_absolute_path(p)) {
abs_str = path_append(pwd, p);
free(p);
p = abs_str;

6
sshd.c
View File

@ -774,7 +774,7 @@ privsep_preauth(Authctxt *authctxt)
else {
char** argv = privsep_child_cmdline(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);
}
close(pmonitor->m_recvfd);
@ -880,7 +880,7 @@ privsep_postauth(Authctxt *authctxt)
else {
char** argv = privsep_child_cmdline(1);
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);
}
@ -1545,7 +1545,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
error("posix_spawn initialization failed");
else {
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_spawnattr_destroy(&attributes);
}