mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-31 01:35:11 +02:00
Decouple key-agent and privileged-agent use in sshd (#173)
PowerShell/Win32-OpenSSH#766 PowerShell/Win32-OpenSSH#783
This commit is contained in:
parent
ad17ff1b74
commit
f8f5e45f02
@ -226,38 +226,45 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
|
|||||||
|
|
||||||
#elif defined(WINDOWS)
|
#elif defined(WINDOWS)
|
||||||
/*
|
/*
|
||||||
* Authenticate on Windows - Pass credentials to ssh-agent and retrieve token
|
* Authenticate on Windows - Call LogonUser and retrieve user token
|
||||||
* upon successful authentication
|
|
||||||
* TODO - password is sent in plain text over IPC. Consider implications.
|
|
||||||
*/
|
*/
|
||||||
int sys_auth_passwd(Authctxt *authctxt, const char *password)
|
int sys_auth_passwd(Authctxt *authctxt, const char *password)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg = NULL;
|
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *pwd_utf16 = NULL, *tmp;
|
||||||
size_t blen = 0;
|
HANDLE token = NULL;
|
||||||
DWORD token = 0;
|
|
||||||
extern int auth_sock;
|
|
||||||
int r = 0;
|
int r = 0;
|
||||||
int ssh_request_reply(int, struct sshbuf *, struct sshbuf *);
|
|
||||||
|
|
||||||
msg = sshbuf_new();
|
if ((user_utf16 = utf8_to_utf16(authctxt->pw->pw_name)) == NULL ||
|
||||||
if (!msg)
|
(pwd_utf16 = utf8_to_utf16(password)) == NULL) {
|
||||||
fatal("%s: out of memory", __func__);
|
fatal("out of memory");
|
||||||
|
|
||||||
if (sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE) != 0 ||
|
|
||||||
sshbuf_put_cstring(msg, PASSWD_AUTH_REQUEST) != 0 ||
|
|
||||||
sshbuf_put_cstring(msg, authctxt->pw->pw_name) != 0 ||
|
|
||||||
sshbuf_put_cstring(msg, password) != 0 ||
|
|
||||||
ssh_request_reply(auth_sock, msg, msg) != 0 ||
|
|
||||||
sshbuf_get_u32(msg, &token) != 0) {
|
|
||||||
debug("auth agent did not authorize client %s", authctxt->user);
|
|
||||||
r = 0;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
authctxt->methoddata = (void*)(INT_PTR)token;
|
|
||||||
|
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
|
||||||
|
udom_utf16 = tmp + 1;
|
||||||
|
*tmp = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT,
|
||||||
|
LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
|
||||||
|
if (GetLastError() == ERROR_PASSWORD_MUST_CHANGE)
|
||||||
|
/*
|
||||||
|
* TODO - need to add support to force password change
|
||||||
|
* by sending back SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
|
||||||
|
*/
|
||||||
|
error("password for user %s has expired", authctxt->pw->pw_name);
|
||||||
|
else
|
||||||
|
debug("failed to logon user: %ls domain: %ls error:%d", user_utf16, udom_utf16, GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
authctxt->auth_token = (void*)(INT_PTR)token;
|
||||||
r = 1;
|
r = 1;
|
||||||
done:
|
done:
|
||||||
if (msg)
|
if (user_utf16)
|
||||||
sshbuf_free(msg);
|
free(user_utf16);
|
||||||
|
if (pwd_utf16)
|
||||||
|
SecureZeroMemory(pwd_utf16, sizeof(wchar_t) * wcslen(pwd_utf16));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
#endif /* WINDOWS */
|
#endif /* WINDOWS */
|
||||||
|
4
auth.h
4
auth.h
@ -78,7 +78,9 @@ struct Authctxt {
|
|||||||
#endif
|
#endif
|
||||||
Buffer *loginmsg;
|
Buffer *loginmsg;
|
||||||
void *methoddata;
|
void *methoddata;
|
||||||
|
#ifdef WINDOWS
|
||||||
|
void *auth_token;
|
||||||
|
#endif
|
||||||
struct sshkey **prev_userkeys;
|
struct sshkey **prev_userkeys;
|
||||||
u_int nprev_userkeys;
|
u_int nprev_userkeys;
|
||||||
};
|
};
|
||||||
|
@ -200,54 +200,14 @@ userauth_pubkey(struct ssh *ssh)
|
|||||||
/* test for correct signature */
|
/* test for correct signature */
|
||||||
authenticated = 0;
|
authenticated = 0;
|
||||||
|
|
||||||
#ifdef WINDOWS
|
|
||||||
/* Pass key challenge material to ssh-agent to retrieve token upon successful authentication */
|
|
||||||
{
|
|
||||||
struct sshbuf *msg = NULL;
|
|
||||||
u_char *blob = NULL;
|
|
||||||
size_t blen = 0;
|
|
||||||
DWORD token = 0;
|
|
||||||
extern int auth_sock;
|
|
||||||
int r = 0;
|
|
||||||
int ssh_request_reply(int , struct sshbuf *, struct sshbuf *);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
msg = sshbuf_new();
|
|
||||||
if (!msg)
|
|
||||||
fatal("%s: out of memory", __func__);
|
|
||||||
if ((r = sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE)) != 0 ||
|
|
||||||
(r = sshbuf_put_cstring(msg, PUBKEY_AUTH_REQUEST)) != 0 ||
|
|
||||||
(r = sshkey_to_blob(key, &blob, &blen)) != 0 ||
|
|
||||||
(r = sshbuf_put_string(msg, blob, blen)) != 0 ||
|
|
||||||
(r = sshbuf_put_cstring(msg, authctxt->pw->pw_name)) != 0 ||
|
|
||||||
(r = sshbuf_put_string(msg, sig, slen)) != 0 ||
|
|
||||||
(r = sshbuf_put_string(msg, sshbuf_ptr(b), sshbuf_len(b))) != 0 ||
|
|
||||||
(r = ssh_request_reply(auth_sock, msg, msg)) != 0 ||
|
|
||||||
(r = sshbuf_get_u32(msg, &token)) != 0) {
|
|
||||||
debug("auth agent did not authorize client %s", authctxt->user);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug3("auth agent authenticated %s", authctxt->user);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (blob)
|
|
||||||
free(blob);
|
|
||||||
if (msg)
|
|
||||||
sshbuf_free(msg);
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
authenticated = 1;
|
|
||||||
authctxt->methoddata = (void*)(INT_PTR)token;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* !WINDOWS */
|
|
||||||
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
|
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
|
||||||
|
#ifdef WINDOWS
|
||||||
|
(authctxt->auth_token = mm_auth_pubkey(authctxt->pw->pw_name,
|
||||||
|
key, sig, slen, b)) != NULL) {
|
||||||
|
#else
|
||||||
PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
|
PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
|
||||||
sshbuf_len(b), ssh->compat)) == 0) {
|
sshbuf_len(b), ssh->compat)) == 0) {
|
||||||
|
#endif
|
||||||
authenticated = 1;
|
authenticated = 1;
|
||||||
/* Record the successful key to prevent reuse */
|
/* Record the successful key to prevent reuse */
|
||||||
auth2_record_userkey(authctxt, key);
|
auth2_record_userkey(authctxt, key);
|
||||||
@ -255,7 +215,6 @@ userauth_pubkey(struct ssh *ssh)
|
|||||||
}
|
}
|
||||||
sshbuf_free(b);
|
sshbuf_free(b);
|
||||||
free(sig);
|
free(sig);
|
||||||
#endif /* !WINDOWS */
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
|
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
|
||||||
|
9
authfd.h
9
authfd.h
@ -43,6 +43,7 @@ int ssh_agent_sign(int sock, struct sshkey *key,
|
|||||||
const u_char *data, size_t datalen, const char *alg, u_int compat);
|
const u_char *data, size_t datalen, const char *alg, u_int compat);
|
||||||
|
|
||||||
/* Messages for the authentication agent connection. */
|
/* Messages for the authentication agent connection. */
|
||||||
|
/* Message Id 0 is reserved */
|
||||||
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
||||||
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
||||||
#define SSH_AGENTC_RSA_CHALLENGE 3
|
#define SSH_AGENTC_RSA_CHALLENGE 3
|
||||||
@ -88,12 +89,4 @@ int ssh_agent_sign(int sock, struct sshkey *key,
|
|||||||
#define SSH_AGENT_RSA_SHA2_256 0x02
|
#define SSH_AGENT_RSA_SHA2_256 0x02
|
||||||
#define SSH_AGENT_RSA_SHA2_512 0x04
|
#define SSH_AGENT_RSA_SHA2_512 0x04
|
||||||
|
|
||||||
/*
|
|
||||||
* Following are used in Windows implementation
|
|
||||||
* ssh-agent in Windows also serves user authentication
|
|
||||||
*/
|
|
||||||
#define SSH_AGENT_AUTHENTICATE 200
|
|
||||||
#define PUBKEY_AUTH_REQUEST "pubkey"
|
|
||||||
#define PASSWD_AUTH_REQUEST "password"
|
|
||||||
|
|
||||||
#endif /* AUTHFD_H */
|
#endif /* AUTHFD_H */
|
||||||
|
@ -246,6 +246,7 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_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)contrib\win32\win32compat\win32_monitor_wrap.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="version.rc" />
|
<ResourceCompile Include="version.rc" />
|
||||||
|
@ -150,6 +150,9 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_monitor_wrap.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="version.rc">
|
<ResourceCompile Include="version.rc">
|
||||||
|
@ -119,4 +119,5 @@ Subsystem sftp sftp-server.exe
|
|||||||
# X11Forwarding no
|
# X11Forwarding no
|
||||||
# AllowTcpForwarding no
|
# AllowTcpForwarding no
|
||||||
# ForceCommand cvs server
|
# ForceCommand cvs server
|
||||||
# PubkeyAcceptedKeyTypes ssh-ed25519*
|
# PubkeyAcceptedKeyTypes ssh-ed25519*
|
||||||
|
hostkeyagent \\.\pipe\openssh-ssh-agent
|
@ -114,7 +114,6 @@ int
|
|||||||
fileio_connect(struct w32_io* pio, char* name)
|
fileio_connect(struct w32_io* pio, char* name)
|
||||||
{
|
{
|
||||||
wchar_t* name_w = NULL;
|
wchar_t* name_w = NULL;
|
||||||
wchar_t pipe_name[PATH_MAX];
|
|
||||||
HANDLE h = INVALID_HANDLE_VALUE;
|
HANDLE h = INVALID_HANDLE_VALUE;
|
||||||
int ret = 0, r;
|
int ret = 0, r;
|
||||||
|
|
||||||
@ -129,16 +128,9 @@ fileio_connect(struct w32_io* pio, char* name)
|
|||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
r = _snwprintf_s(pipe_name, PATH_MAX, PATH_MAX, L"\\\\.\\pipe\\%ls", name_w);
|
|
||||||
if (r < 0 || r >= PATH_MAX) {
|
|
||||||
debug3("cannot create pipe name with %s", name);
|
|
||||||
errno = EOTHER;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
h = CreateFileW(pipe_name, GENERIC_READ | GENERIC_WRITE, 0,
|
h = CreateFileW(name_w, GENERIC_READ | GENERIC_WRITE, 0,
|
||||||
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, NULL);
|
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, NULL);
|
||||||
|
|
||||||
if (h != INVALID_HANDLE_VALUE)
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
|
8
contrib/win32/win32compat/priv-agent.h
Normal file
8
contrib/win32/win32compat/priv-agent.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Definitions for IPC between sshd and privileged agent
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define SSH_PRIV_AGENT_MSG_ID 0
|
||||||
|
#define PUBKEY_AUTH_REQUEST "pubkey"
|
||||||
|
#define LOAD_USER_PROFILE_REQUEST "loadprofile"
|
@ -16,6 +16,6 @@ int process_request_identities(struct sshbuf*, struct sshbuf*, struct agent_conn
|
|||||||
int process_sign_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
int process_sign_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
||||||
int process_remove_key(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
int process_remove_key(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
||||||
int process_remove_all(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
int process_remove_all(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
||||||
int process_authagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
int process_privagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
||||||
|
|
||||||
/* auth */
|
/* auth */
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
static HANDLE ioc_port = NULL;
|
static HANDLE ioc_port = NULL;
|
||||||
static BOOL debug_mode = FALSE;
|
static BOOL debug_mode = FALSE;
|
||||||
|
|
||||||
#define AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-agent"
|
#define AGENT_PIPE_ID L"\\\\.\\pipe\\openssh-ssh-agent"
|
||||||
|
|
||||||
static HANDLE event_stop_agent;
|
static HANDLE event_stop_agent;
|
||||||
static OVERLAPPED ol;
|
static OVERLAPPED ol;
|
||||||
@ -168,12 +168,14 @@ agent_cleanup_connection(struct agent_connection* con)
|
|||||||
{
|
{
|
||||||
debug("connection %p clean up", con);
|
debug("connection %p clean up", con);
|
||||||
CloseHandle(con->pipe_handle);
|
CloseHandle(con->pipe_handle);
|
||||||
if (con->hProfile)
|
if (con->profile_handle)
|
||||||
UnloadUserProfile(con->auth_token, con->hProfile);
|
UnloadUserProfile(con->profile_token, con->profile_handle);
|
||||||
if (con->auth_token)
|
if (con->profile_token)
|
||||||
CloseHandle(con->auth_token);
|
CloseHandle(con->profile_token);
|
||||||
if (con->client_impersonation_token)
|
if (con->client_impersonation_token)
|
||||||
CloseHandle(con->client_impersonation_token);
|
CloseHandle(con->client_impersonation_token);
|
||||||
|
if (con->client_process_handle)
|
||||||
|
CloseHandle(con->client_process_handle);
|
||||||
free(con);
|
free(con);
|
||||||
CloseHandle(ioc_port);
|
CloseHandle(ioc_port);
|
||||||
ioc_port = NULL;
|
ioc_port = NULL;
|
||||||
@ -251,13 +253,13 @@ get_con_client_info(struct agent_connection* con)
|
|||||||
DWORD sshd_sid_len = 0;
|
DWORD sshd_sid_len = 0;
|
||||||
PSID sshd_sid = NULL;
|
PSID sshd_sid = NULL;
|
||||||
SID_NAME_USE nuse;
|
SID_NAME_USE nuse;
|
||||||
HANDLE client_primary_token = NULL, client_impersonation_token = NULL, client_proc_handle = NULL;
|
HANDLE client_primary_token = NULL, client_impersonation_token = NULL, client_process_handle = NULL;
|
||||||
TOKEN_USER* info = NULL;
|
TOKEN_USER* info = NULL;
|
||||||
BOOL isMember = FALSE;
|
BOOL isMember = FALSE;
|
||||||
|
|
||||||
if (GetNamedPipeClientProcessId(con->pipe_handle, &client_pid) == FALSE ||
|
if (GetNamedPipeClientProcessId(con->pipe_handle, &client_pid) == FALSE ||
|
||||||
(client_proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, client_pid)) == NULL ||
|
(client_process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL ||
|
||||||
OpenProcessToken(client_proc_handle, TOKEN_QUERY | TOKEN_DUPLICATE, &client_primary_token) == FALSE ||
|
OpenProcessToken(client_process_handle, TOKEN_QUERY | TOKEN_DUPLICATE, &client_primary_token) == FALSE ||
|
||||||
DuplicateToken(client_primary_token, SecurityImpersonation, &client_impersonation_token) == FALSE) {
|
DuplicateToken(client_primary_token, SecurityImpersonation, &client_impersonation_token) == FALSE) {
|
||||||
error("cannot retrieve client impersonatin token");
|
error("cannot retrieve client impersonatin token");
|
||||||
goto done;
|
goto done;
|
||||||
@ -341,15 +343,19 @@ done:
|
|||||||
free(ref_dom);
|
free(ref_dom);
|
||||||
if (info)
|
if (info)
|
||||||
free(info);
|
free(info);
|
||||||
if (client_proc_handle)
|
|
||||||
CloseHandle(client_proc_handle);
|
|
||||||
if (client_primary_token)
|
if (client_primary_token)
|
||||||
CloseHandle(client_primary_token);
|
CloseHandle(client_primary_token);
|
||||||
|
|
||||||
if (r == 0)
|
if (r == 0) {
|
||||||
|
con->client_process_handle = client_process_handle;
|
||||||
con->client_impersonation_token = client_impersonation_token;
|
con->client_impersonation_token = client_impersonation_token;
|
||||||
else if (client_impersonation_token)
|
}
|
||||||
CloseHandle(client_impersonation_token);
|
else {
|
||||||
|
if (client_process_handle)
|
||||||
|
CloseHandle(client_process_handle);
|
||||||
|
if (client_impersonation_token)
|
||||||
|
CloseHandle(client_impersonation_token);
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,18 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#define MAX_MESSAGE_SIZE 256 * 1024
|
#define MAX_MESSAGE_SIZE 256 * 1024
|
||||||
|
|
||||||
#define SSH_ROOT L"SOFTWARE\\SSH"
|
#define SSH_ROOT L"SOFTWARE\\OpenSSH"
|
||||||
#define SSH_AGENT_ROOT SSH_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_ROOT L"\\" SSH_KEYS_KEY
|
#define SSH_KEYS_ROOT SSH_AGENT_ROOT L"\\" SSH_KEYS_KEY
|
||||||
|
|
||||||
#define HEADER_SIZE 4
|
#define HEADER_SIZE 4
|
||||||
|
|
||||||
struct agent_connection {
|
struct agent_connection {
|
||||||
OVERLAPPED ol;
|
OVERLAPPED ol;
|
||||||
HANDLE pipe_handle;
|
HANDLE pipe_handle;
|
||||||
HANDLE client_impersonation_token;
|
HANDLE client_impersonation_token;
|
||||||
|
HANDLE client_process_handle;
|
||||||
struct {
|
struct {
|
||||||
DWORD num_bytes;
|
DWORD num_bytes;
|
||||||
DWORD transferred;
|
DWORD transferred;
|
||||||
@ -36,8 +37,9 @@ struct agent_connection {
|
|||||||
SYSTEM, /* client is running as System */
|
SYSTEM, /* client is running as System */
|
||||||
SERVICE, /* client is running as LS or NS */
|
SERVICE, /* client is running as LS or NS */
|
||||||
} client_type;
|
} client_type;
|
||||||
HANDLE auth_token;
|
/* user profile related members */
|
||||||
HANDLE hProfile;
|
HANDLE profile_token;
|
||||||
|
HANDLE profile_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);
|
void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);
|
||||||
|
@ -72,6 +72,12 @@ mm_user_key_allowed(struct passwd *pw, Key *k, int i)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* mm_auth_pubkey(const char* user_name, const struct sshkey *key,
|
||||||
|
const u_char *sig, size_t slen, struct sshbuf* b)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
kexgex_server(struct ssh * sh) {
|
kexgex_server(struct ssh * sh) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "agent-request.h"
|
#include "agent-request.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "inc\utf.h"
|
#include "inc\utf.h"
|
||||||
|
#include "..\priv-agent.h"
|
||||||
|
|
||||||
#pragma warning(push, 3)
|
#pragma warning(push, 3)
|
||||||
|
|
||||||
@ -83,9 +84,11 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static HANDLE
|
||||||
LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
|
LoadProfile(HANDLE user_token, wchar_t* user, wchar_t* domain) {
|
||||||
PROFILEINFOW profileInfo;
|
PROFILEINFOW profileInfo;
|
||||||
|
HANDLE ret = NULL;
|
||||||
|
|
||||||
profileInfo.dwFlags = PI_NOUI;
|
profileInfo.dwFlags = PI_NOUI;
|
||||||
profileInfo.lpProfilePath = NULL;
|
profileInfo.lpProfilePath = NULL;
|
||||||
profileInfo.lpUserName = user;
|
profileInfo.lpUserName = user;
|
||||||
@ -96,12 +99,16 @@ LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
|
|||||||
profileInfo.dwSize = sizeof(profileInfo);
|
profileInfo.dwSize = sizeof(profileInfo);
|
||||||
EnablePrivilege("SeBackupPrivilege", 1);
|
EnablePrivilege("SeBackupPrivilege", 1);
|
||||||
EnablePrivilege("SeRestorePrivilege", 1);
|
EnablePrivilege("SeRestorePrivilege", 1);
|
||||||
if (LoadUserProfileW(con->auth_token, &profileInfo) == FALSE)
|
if (LoadUserProfileW(user_token, &profileInfo) == FALSE) {
|
||||||
debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError());
|
debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
con->hProfile = profileInfo.hProfile;
|
ret = profileInfo.hProfile;
|
||||||
|
done:
|
||||||
EnablePrivilege("SeBackupPrivilege", 0);
|
EnablePrivilege("SeBackupPrivilege", 0);
|
||||||
EnablePrivilege("SeRestorePrivilege", 0);
|
EnablePrivilege("SeRestorePrivilege", 0);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_USER_LEN 64
|
#define MAX_USER_LEN 64
|
||||||
@ -238,73 +245,13 @@ done:
|
|||||||
return dup_t;
|
return dup_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO - SecureZeroMemory password */
|
|
||||||
int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
|
||||||
char *user = NULL, *domain = NULL, *pwd = NULL;
|
|
||||||
size_t user_len, pwd_len;
|
|
||||||
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *pwd_utf16 = NULL, *tmp;
|
|
||||||
int r = -1;
|
|
||||||
HANDLE token = 0, dup_token;
|
|
||||||
|
|
||||||
if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
|
|
||||||
sshbuf_get_cstring(request, &pwd, &pwd_len) != 0 ||
|
|
||||||
user_len == 0 ||
|
|
||||||
pwd_len == 0 ||
|
|
||||||
user_len > MAX_USER_LEN + MAX_FQDN_LEN ||
|
|
||||||
pwd_len > MAX_PW_LEN) {
|
|
||||||
debug("bad password auth request");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((user_utf16 = utf8_to_utf16(user)) == NULL ||
|
|
||||||
(pwd_utf16 = utf8_to_utf16(pwd)) == NULL) {
|
|
||||||
debug("out of memory");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((tmp = wcschr(user_utf16, L'@') ) != NULL ) {
|
|
||||||
udom_utf16 = tmp + 1;
|
|
||||||
*tmp = L'\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
|
|
||||||
debug("failed to logon user: %ls domain: %ls", user_utf16, udom_utf16);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dup_token = duplicate_token_for_client(con, token)) == NULL)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
con->auth_token = token;
|
|
||||||
LoadProfile(con, user_utf16, udom_utf16);
|
|
||||||
r = 0;
|
|
||||||
done:
|
|
||||||
/* TODO Fix this hacky protocol*/
|
|
||||||
if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
|
|
||||||
r = 0;
|
|
||||||
|
|
||||||
if (user)
|
|
||||||
free(user);
|
|
||||||
if (pwd)
|
|
||||||
free(pwd);
|
|
||||||
if (user_utf16)
|
|
||||||
free(user_utf16);
|
|
||||||
if (pwd_utf16)
|
|
||||||
free(pwd_utf16);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, *sig, *blob;
|
char *key_blob, *user, *sig, *blob;
|
||||||
size_t key_blob_len, user_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, dup_token = NULL;
|
HANDLE token = NULL, dup_token = NULL;
|
||||||
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *tmp;
|
wchar_t *user_utf16 = NULL;
|
||||||
PWSTR wuser_home = NULL;
|
PWSTR wuser_home = NULL;
|
||||||
|
|
||||||
|
|
||||||
@ -346,14 +293,6 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
|
|||||||
if (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)
|
if (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
con->auth_token = token;
|
|
||||||
token = NULL;
|
|
||||||
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:
|
||||||
/* TODO Fix this hacky protocol*/
|
/* TODO Fix this hacky protocol*/
|
||||||
@ -373,7 +312,60 @@ done:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_authagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
int process_loadprofile_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
||||||
|
int r = 0, success = 0;
|
||||||
|
char *user;
|
||||||
|
size_t user_len;
|
||||||
|
u_int32_t user_token_int = 0;
|
||||||
|
HANDLE user_token = NULL;
|
||||||
|
wchar_t *user_utf16 = NULL, *dom_utf16 = NULL, *tmp;
|
||||||
|
|
||||||
|
/* is profile already loaded */
|
||||||
|
if (con->profile_handle) {
|
||||||
|
success = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
|
||||||
|
user_len > MAX_USER_LEN ||
|
||||||
|
sshbuf_get_u32(request, &user_token_int) != 0){
|
||||||
|
debug("invalid loadprofile request");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DuplicateHandle(con->client_process_handle, (HANDLE)(INT_PTR)user_token_int, GetCurrentProcess(),
|
||||||
|
&user_token, TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, FALSE, 0) == FALSE) {
|
||||||
|
debug("cannot duplicate user token, error: %d", GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
|
||||||
|
debug("out of memory");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* split user and domain */
|
||||||
|
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
|
||||||
|
dom_utf16 = tmp + 1;
|
||||||
|
*tmp = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((con->profile_handle = LoadProfile(user_token, user_utf16, dom_utf16)) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
con->profile_token = user_token;
|
||||||
|
user_token = NULL;
|
||||||
|
success = 1;
|
||||||
|
done:
|
||||||
|
if (sshbuf_put_u8(response, success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE) != 0)
|
||||||
|
r = -1;
|
||||||
|
|
||||||
|
if (user_token)
|
||||||
|
CloseHandle(user_token);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_privagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
||||||
char *opn;
|
char *opn;
|
||||||
size_t opn_len;
|
size_t opn_len;
|
||||||
if (sshbuf_get_string_direct(request, &opn, &opn_len) != 0) {
|
if (sshbuf_get_string_direct(request, &opn, &opn_len) != 0) {
|
||||||
@ -383,14 +375,14 @@ int process_authagent_request(struct sshbuf* request, struct sshbuf* response, s
|
|||||||
|
|
||||||
/* allow only admins and NT Service\sshd to send auth requests */
|
/* allow only admins and NT Service\sshd to send auth requests */
|
||||||
if (con->client_type != SSHD_SERVICE && con->client_type != ADMIN_USER) {
|
if (con->client_type != SSHD_SERVICE && con->client_type != ADMIN_USER) {
|
||||||
error("cannot authenticate: client process is not admin or sshd");
|
error("cannot process request: client process is not admin or sshd");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0)
|
if (memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0)
|
||||||
return process_pubkeyauth_request(request, response, con);
|
return process_pubkeyauth_request(request, response, con);
|
||||||
else if (memcmp(opn, PASSWD_AUTH_REQUEST, opn_len) == 0)
|
else if (memcmp(opn, LOAD_USER_PROFILE_REQUEST, opn_len) == 0)
|
||||||
return process_passwordauth_request(request, response, con);
|
return process_loadprofile_request(request, response, con);
|
||||||
else {
|
else {
|
||||||
debug("unknown auth request: %s", opn);
|
debug("unknown auth request: %s", opn);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
#include "agent-request.h"
|
#include "agent-request.h"
|
||||||
|
#include "..\priv-agent.h"
|
||||||
|
|
||||||
#pragma warning(push, 3)
|
#pragma warning(push, 3)
|
||||||
|
|
||||||
@ -168,8 +169,8 @@ process_request(struct agent_connection* con)
|
|||||||
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
||||||
r = process_remove_all(request, response, con);
|
r = process_remove_all(request, response, con);
|
||||||
break;
|
break;
|
||||||
case SSH_AGENT_AUTHENTICATE:
|
case SSH_PRIV_AGENT_MSG_ID:
|
||||||
r = process_authagent_request(request, response, con);
|
r = process_privagent_request(request, response, con);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
debug("unknown agent request %d", type);
|
debug("unknown agent request %d", type);
|
||||||
|
214
contrib/win32/win32compat/win32_monitor_wrap.c
Normal file
214
contrib/win32/win32compat/win32_monitor_wrap.c
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
|
||||||
|
* mm_* routines that delegate privileged operations to privileged
|
||||||
|
* agent.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Microsoft Corp.
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Microsoft openssh win32 port
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "openbsd-compat/sys-queue.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "ssh.h"
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
#include "dh.h"
|
||||||
|
#endif
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "key.h"
|
||||||
|
#include "cipher.h"
|
||||||
|
#include "kex.h"
|
||||||
|
#include "hostfile.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "auth-options.h"
|
||||||
|
#include "packet.h"
|
||||||
|
#include "mac.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "auth-pam.h"
|
||||||
|
#include "monitor_wrap.h"
|
||||||
|
#include "atomicio.h"
|
||||||
|
#include "monitor_fdpass.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "uuencode.h"
|
||||||
|
|
||||||
|
#include "channels.h"
|
||||||
|
#include "session.h"
|
||||||
|
#include "servconf.h"
|
||||||
|
|
||||||
|
#include "ssherr.h"
|
||||||
|
#include "priv-agent.h"
|
||||||
|
#include "authfd.h"
|
||||||
|
|
||||||
|
int priv_agent_sock = -1;
|
||||||
|
int ssh_request_reply(int, struct sshbuf *, struct sshbuf *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get socket connected to privileged agent
|
||||||
|
* In Windows, this is implemented within ssh-agent
|
||||||
|
* that server both as a key-agent (like in Unix) and
|
||||||
|
* privileged agent.
|
||||||
|
* This is a temporary accomodation until Windows has
|
||||||
|
* Unix like privilege separation (monitor and less
|
||||||
|
* privileged worker)
|
||||||
|
*/
|
||||||
|
int get_priv_agent_sock()
|
||||||
|
{
|
||||||
|
extern int auth_sock;
|
||||||
|
char env_value[12]; /* enough to accomodate "ssh-agent"*/
|
||||||
|
size_t tmp;
|
||||||
|
|
||||||
|
if (priv_agent_sock != -1)
|
||||||
|
return priv_agent_sock;
|
||||||
|
|
||||||
|
/* check if auth_sock is populated and connected to "ssh-agent"*/
|
||||||
|
if (auth_sock != -1 &&
|
||||||
|
getenv_s(&tmp, env_value, 12, SSH_AUTHSOCKET_ENV_NAME) == 0 &&
|
||||||
|
strncmp(env_value, "ssh-agent", 12) == 0 )
|
||||||
|
priv_agent_sock = auth_sock;
|
||||||
|
else {
|
||||||
|
struct sockaddr_un sunaddr;
|
||||||
|
int sock;
|
||||||
|
|
||||||
|
memset(&sunaddr, 0, sizeof(sunaddr));
|
||||||
|
sunaddr.sun_family = AF_UNIX;
|
||||||
|
strlcpy(sunaddr.sun_path, "\\\\.\\pipe\\openssh-ssh-agent", sizeof(sunaddr.sun_path));
|
||||||
|
|
||||||
|
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||||
|
debug("%s: unable to create AF_UNIX socket, errno:%d", __func__, errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close on exec */
|
||||||
|
if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1 ||
|
||||||
|
connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
|
||||||
|
close(sock);
|
||||||
|
debug("%s: unable to connect to privileged agent, errno:%d", __func__, errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv_agent_sock = sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv_agent_sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* mm_auth_pubkey(const char* user_name, const struct sshkey *key,
|
||||||
|
const u_char *sig, size_t slen, struct sshbuf* b)
|
||||||
|
{
|
||||||
|
/* Pass key challenge material to privileged agent to retrieve token upon successful authentication */
|
||||||
|
struct sshbuf *msg = NULL;
|
||||||
|
u_char *blob = NULL;
|
||||||
|
size_t blen = 0;
|
||||||
|
DWORD token = 0;
|
||||||
|
int agent_fd;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if ((agent_fd = get_priv_agent_sock()) == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
msg = sshbuf_new();
|
||||||
|
if (!msg)
|
||||||
|
fatal("%s: out of memory", __func__);
|
||||||
|
if (sshbuf_put_u8(msg, SSH_PRIV_AGENT_MSG_ID) != 0 ||
|
||||||
|
sshbuf_put_cstring(msg, PUBKEY_AUTH_REQUEST) != 0 ||
|
||||||
|
sshkey_to_blob(key, &blob, &blen) != 0 ||
|
||||||
|
sshbuf_put_string(msg, blob, blen) != 0 ||
|
||||||
|
sshbuf_put_cstring(msg, user_name) != 0 ||
|
||||||
|
sshbuf_put_string(msg, sig, slen) != 0 ||
|
||||||
|
sshbuf_put_string(msg, sshbuf_ptr(b), sshbuf_len(b)) != 0 ||
|
||||||
|
ssh_request_reply(agent_fd, msg, msg) != 0) {
|
||||||
|
debug("unable to send pubkeyauth request");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sshbuf_get_u32(msg, &token) != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
debug3("%s authenticated via pubkey", user_name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (blob)
|
||||||
|
free(blob);
|
||||||
|
if (msg)
|
||||||
|
sshbuf_free(msg);
|
||||||
|
|
||||||
|
return (void*)(INT_PTR)token;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_load_profile(const char* user_name, u_int token)
|
||||||
|
{
|
||||||
|
struct sshbuf *msg = NULL;
|
||||||
|
int agent_fd;
|
||||||
|
u_char result = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if ((agent_fd = get_priv_agent_sock()) == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
msg = sshbuf_new();
|
||||||
|
if (!msg)
|
||||||
|
fatal("%s: out of memory", __func__);
|
||||||
|
if (sshbuf_put_u8(msg, SSH_PRIV_AGENT_MSG_ID) != 0 ||
|
||||||
|
sshbuf_put_cstring(msg, LOAD_USER_PROFILE_REQUEST) != 0 ||
|
||||||
|
sshbuf_put_cstring(msg, user_name) != 0 ||
|
||||||
|
sshbuf_put_u32(msg, token) != 0 ||
|
||||||
|
ssh_request_reply(agent_fd, msg, msg) != 0) {
|
||||||
|
debug("unable to send loadprofile request %s", user_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sshbuf_get_u8(msg, &result) != 0 || result == SSH_AGENT_FAILURE) {
|
||||||
|
debug("agent failed to load profile for user %s", user_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
@ -51,7 +51,7 @@ wmain(int argc, wchar_t **wargv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getenv("SSH_AUTH_SOCK") == NULL)
|
if (getenv("SSH_AUTH_SOCK") == NULL)
|
||||||
_putenv("SSH_AUTH_SOCK=ssh-agent");
|
_putenv("SSH_AUTH_SOCK=\\\\.\\pipe\\openssh-ssh-agent");
|
||||||
|
|
||||||
w32posix_initialize();
|
w32posix_initialize();
|
||||||
|
|
||||||
|
@ -108,9 +108,6 @@ int sshd_main(int argc, wchar_t **wargv) {
|
|||||||
argv[i] = utf16_to_utf8(wargv[i]);
|
argv[i] = utf16_to_utf8(wargv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getenv("SSH_AUTH_SOCK") == NULL)
|
|
||||||
_putenv("SSH_AUTH_SOCK=ssh-agent");
|
|
||||||
|
|
||||||
w32posix_initialize();
|
w32posix_initialize();
|
||||||
if (getenv("SSHD_REMSOC"))
|
if (getenv("SSHD_REMSOC"))
|
||||||
is_child = 1;
|
is_child = 1;
|
||||||
|
@ -98,4 +98,9 @@ int mm_bsdauth_respond(void *, u_int, char **);
|
|||||||
int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
|
int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
|
||||||
int mm_skey_respond(void *, u_int, char **);
|
int mm_skey_respond(void *, u_int, char **);
|
||||||
|
|
||||||
|
/* Windows specific */
|
||||||
|
void* mm_auth_pubkey(const char*, const struct sshkey *, const u_char *, size_t,
|
||||||
|
struct sshbuf*);
|
||||||
|
int mm_load_profile(const char*, u_int );
|
||||||
|
|
||||||
#endif /* _MM_WRAP_H_ */
|
#endif /* _MM_WRAP_H_ */
|
||||||
|
@ -125,4 +125,5 @@ PubkeyAcceptedKeyTypes ssh-ed25519*
|
|||||||
#DenyUsers denyuser1 deny*2 denyuse?3,
|
#DenyUsers denyuser1 deny*2 denyuse?3,
|
||||||
#AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
|
#AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
|
||||||
#DenyGroups denygroup1 denygr*p2 deny?rou?3
|
#DenyGroups denygroup1 denygr*p2 deny?rou?3
|
||||||
#AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
|
#AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
|
||||||
|
hostkeyagent \\.\pipe\openssh-ssh-agent
|
||||||
|
@ -605,8 +605,9 @@ derelativise_path(const char *path)
|
|||||||
return xstrdup("none");
|
return xstrdup("none");
|
||||||
expanded = tilde_expand_filename(path, getuid());
|
expanded = tilde_expand_filename(path, getuid());
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
/* Windows absolute paths have a drive letter followed by :*/
|
/* Windows absolute paths - \abc, /abc, c:\abc, c:/abc*/
|
||||||
if (*expanded != '\0' && expanded[1] == ':')
|
if (*expanded == '/' || *expanded == '\\' ||
|
||||||
|
(*expanded != '\0' && expanded[1] == ':'))
|
||||||
#else /* !WINDOWS */
|
#else /* !WINDOWS */
|
||||||
if (*expanded == '/')
|
if (*expanded == '/')
|
||||||
#endif /* !WINDOWS */
|
#endif /* !WINDOWS */
|
||||||
|
@ -477,6 +477,9 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
|||||||
*cmd = '\0';
|
*cmd = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* load user profile */
|
||||||
|
mm_load_profile(s->pw->pw_name, ((INT_PTR)s->authctxt->auth_token) & 0xffffffff);
|
||||||
|
|
||||||
/* start the process */
|
/* start the process */
|
||||||
{
|
{
|
||||||
memset(&si, 0, sizeof(STARTUPINFO));
|
memset(&si, 0, sizeof(STARTUPINFO));
|
||||||
@ -492,7 +495,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
|||||||
si.hStdError = (HANDLE)w32_fd_to_handle(pipeerr[1]);
|
si.hStdError = (HANDLE)w32_fd_to_handle(pipeerr[1]);
|
||||||
si.lpDesktop = NULL;
|
si.lpDesktop = NULL;
|
||||||
|
|
||||||
hToken = s->authctxt->methoddata;
|
hToken = s->authctxt->auth_token;
|
||||||
|
|
||||||
debug("Executing command: %s", exec_command);
|
debug("Executing command: %s", exec_command);
|
||||||
UTF8_TO_UTF16_FATAL(exec_command_w, exec_command);
|
UTF8_TO_UTF16_FATAL(exec_command_w, exec_command);
|
||||||
|
4
sshd.c
4
sshd.c
@ -1765,9 +1765,7 @@ main(int ac, char **av)
|
|||||||
error("Could not connect to agent \"%s\": %s",
|
error("Could not connect to agent \"%s\": %s",
|
||||||
options.host_key_agent, ssh_err(r));
|
options.host_key_agent, ssh_err(r));
|
||||||
}
|
}
|
||||||
#ifdef WINDOWS /* Windows version always needs and has agent running */
|
|
||||||
have_agent = 1;
|
|
||||||
#endif
|
|
||||||
for (i = 0; i < options.num_host_key_files; i++) {
|
for (i = 0; i < options.num_host_key_files; i++) {
|
||||||
if (options.host_key_files[i] == NULL)
|
if (options.host_key_files[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user