mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-23 14:04:59 +02:00
5/12 C1
This commit is contained in:
parent
fcc3bdcd0a
commit
fedeacacf5
@ -65,7 +65,7 @@ init_listeners() {
|
|||||||
listeners[i].pipe_id = pipe_ids[i];
|
listeners[i].pipe_id = pipe_ids[i];
|
||||||
listeners[i].type = pipe_types[i];
|
listeners[i].type = pipe_types[i];
|
||||||
listeners[i].pipe = INVALID_HANDLE_VALUE;
|
listeners[i].pipe = INVALID_HANDLE_VALUE;
|
||||||
listeners[i].sa.bInheritHandle = TRUE;
|
listeners[i].sa.bInheritHandle = FALSE;
|
||||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(pipe_sddls[i], SDDL_REVISION_1,
|
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(pipe_sddls[i], SDDL_REVISION_1,
|
||||||
&listeners[i].sa.lpSecurityDescriptor, &listeners[i].sa.nLength)) {
|
&listeners[i].sa.lpSecurityDescriptor, &listeners[i].sa.nLength)) {
|
||||||
debug("cannot convert sddl ERROR:%d", GetLastError());
|
debug("cannot convert sddl ERROR:%d", GetLastError());
|
||||||
@ -111,7 +111,6 @@ iocp_work(LPVOID lpParam) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_connection(HANDLE pipe, int type) {
|
process_connection(HANDLE pipe, int type) {
|
||||||
struct agent_connection* con;
|
struct agent_connection* con;
|
||||||
@ -124,7 +123,7 @@ process_connection(HANDLE pipe, int type) {
|
|||||||
con->type = type;
|
con->type = type;
|
||||||
if (CreateIoCompletionPort(pipe, ioc_port, (ULONG_PTR)con, 0) != ioc_port)
|
if (CreateIoCompletionPort(pipe, ioc_port, (ULONG_PTR)con, 0) != ioc_port)
|
||||||
fatal("failed to assign pipe to ioc_port");
|
fatal("failed to assign pipe to ioc_port");
|
||||||
|
|
||||||
agent_connection_on_io(con, 0, &con->ol);
|
agent_connection_on_io(con, 0, &con->ol);
|
||||||
return iocp_work(NULL);
|
return iocp_work(NULL);
|
||||||
}
|
}
|
||||||
@ -185,8 +184,10 @@ agent_listen_loop() {
|
|||||||
else if ((r > WAIT_OBJECT_0) && (r <= (WAIT_OBJECT_0 + NUM_LISTENERS))) {
|
else if ((r > WAIT_OBJECT_0) && (r <= (WAIT_OBJECT_0 + NUM_LISTENERS))) {
|
||||||
/* process incoming connection */
|
/* process incoming connection */
|
||||||
HANDLE con = listeners[r - 1].pipe;
|
HANDLE con = listeners[r - 1].pipe;
|
||||||
|
DWORD client_pid = 0;
|
||||||
listeners[r - 1].pipe = INVALID_HANDLE_VALUE;
|
listeners[r - 1].pipe = INVALID_HANDLE_VALUE;
|
||||||
verbose("client connected on %ls", pipe_ids[r-1]);
|
GetNamedPipeClientProcessId(con, &client_pid);
|
||||||
|
verbose("client pid %d connected on %ls", client_pid, pipe_ids[r-1]);
|
||||||
if (debug_mode) {
|
if (debug_mode) {
|
||||||
process_connection(con, listeners[r - 1].type);
|
process_connection(con, listeners[r - 1].type);
|
||||||
agent_cleanup();
|
agent_cleanup();
|
||||||
@ -201,6 +202,7 @@ agent_listen_loop() {
|
|||||||
si.cb = sizeof(STARTUPINFOW);
|
si.cb = sizeof(STARTUPINFOW);
|
||||||
memset(&si, 0, sizeof(STARTUPINFOW));
|
memset(&si, 0, sizeof(STARTUPINFOW));
|
||||||
GetModuleFileNameW(NULL, module_path, MAX_PATH);
|
GetModuleFileNameW(NULL, module_path, MAX_PATH);
|
||||||
|
SetHandleInformation(con, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
||||||
if ((swprintf_s(path, MAX_PATH, L"%s %d %d", module_path, con, listeners[r - 1].type) == -1 ) ||
|
if ((swprintf_s(path, MAX_PATH, L"%s %d %d", module_path, con, listeners[r - 1].type) == -1 ) ||
|
||||||
(CreateProcessW(NULL, path, NULL, NULL, TRUE,
|
(CreateProcessW(NULL, path, NULL, NULL, TRUE,
|
||||||
DETACHED_PROCESS, NULL, NULL,
|
DETACHED_PROCESS, NULL, NULL,
|
||||||
@ -212,6 +214,7 @@ agent_listen_loop() {
|
|||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
}
|
}
|
||||||
|
SetHandleInformation(con, HANDLE_FLAG_INHERIT, 0);
|
||||||
CloseHandle(con);
|
CloseHandle(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,13 @@ struct agent_connection {
|
|||||||
WRITING,
|
WRITING,
|
||||||
DONE
|
DONE
|
||||||
} state;
|
} state;
|
||||||
|
enum {
|
||||||
|
UNKNOWN = 0,
|
||||||
|
OTHER,
|
||||||
|
LOCAL_SYSTEM,
|
||||||
|
SSHD,
|
||||||
|
NETWORK_SERVICE
|
||||||
|
} client_type;
|
||||||
enum agent_type type;
|
enum agent_type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -114,17 +114,74 @@ void agent_connection_disconnect(struct agent_connection* con) {
|
|||||||
DisconnectNamedPipe(con->connection);
|
DisconnectNamedPipe(con->connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_con_client_type(HANDLE pipe) {
|
||||||
|
int r = -1;
|
||||||
|
wchar_t *sshd_act = L"NT SERVICE\\SSHD", *ref_dom = NULL;
|
||||||
|
PSID sshd_sid = NULL;
|
||||||
|
char system_sid[SECURITY_MAX_SID_SIZE];
|
||||||
|
char ns_sid[SECURITY_MAX_SID_SIZE];
|
||||||
|
DWORD sshd_sid_len = 0, reg_dom_len = 0, info_len = 0, sid_size;
|
||||||
|
SID_NAME_USE nuse;
|
||||||
|
HANDLE token;
|
||||||
|
TOKEN_USER* info = NULL;
|
||||||
|
|
||||||
|
if (ImpersonateNamedPipeClient(pipe) == FALSE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (LookupAccountNameW(NULL, sshd_act, NULL, &sshd_sid_len, NULL, ®_dom_len, &nuse) == TRUE ||
|
||||||
|
(sshd_sid = malloc(sshd_sid_len)) == NULL ||
|
||||||
|
(ref_dom = (wchar_t*)malloc(reg_dom_len * 2)) == NULL ||
|
||||||
|
LookupAccountNameW(NULL, sshd_act, sshd_sid, &sshd_sid_len, ref_dom, ®_dom_len, &nuse) == FALSE ||
|
||||||
|
OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &token) == FALSE ||
|
||||||
|
GetTokenInformation(token, TokenUser, NULL, 0, &info_len) == TRUE ||
|
||||||
|
(info = (TOKEN_USER*)malloc(info_len)) == NULL ||
|
||||||
|
GetTokenInformation(token, TokenUser, info, info_len, &info_len) == FALSE)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
sid_size = SECURITY_MAX_SID_SIZE;
|
||||||
|
if (CreateWellKnownSid(WinLocalSystemSid, NULL, system_sid, &sid_size) == FALSE)
|
||||||
|
goto done;
|
||||||
|
sid_size = SECURITY_MAX_SID_SIZE;
|
||||||
|
if (CreateWellKnownSid(WinNetworkServiceSid, NULL, ns_sid, &sid_size) == FALSE)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (EqualSid(info->User.Sid, system_sid))
|
||||||
|
r = LOCAL_SYSTEM;
|
||||||
|
else if (EqualSid(info->User.Sid, sshd_sid))
|
||||||
|
r = SSHD;
|
||||||
|
else if (EqualSid(info->User.Sid, ns_sid))
|
||||||
|
r = NETWORK_SERVICE;
|
||||||
|
else
|
||||||
|
r = OTHER;
|
||||||
|
|
||||||
|
debug("client type: %d", r);
|
||||||
|
done:
|
||||||
|
if (sshd_sid)
|
||||||
|
free(sshd_sid);
|
||||||
|
if (ref_dom)
|
||||||
|
free(ref_dom);
|
||||||
|
if (info)
|
||||||
|
free(info);
|
||||||
|
RevertToSelf();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_request(struct agent_connection* con) {
|
process_request(struct agent_connection* con) {
|
||||||
int r;
|
int r = -1;
|
||||||
struct sshbuf *request = NULL, *response = NULL;
|
struct sshbuf *request = NULL, *response = NULL;
|
||||||
|
|
||||||
|
if (con->client_type == UNKNOWN)
|
||||||
|
if ((con->client_type = get_con_client_type(con->connection)) == -1)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
|
||||||
request = sshbuf_from(con->io_buf.buf, con->io_buf.num_bytes);
|
request = sshbuf_from(con->io_buf.buf, con->io_buf.num_bytes);
|
||||||
response = sshbuf_new();
|
response = sshbuf_new();
|
||||||
if ((request == NULL) || (response == NULL)) {
|
if ((request == NULL) || (response == NULL))
|
||||||
r = ENOMEM;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
|
|
||||||
if (con->type == KEY_AGENT)
|
if (con->type == KEY_AGENT)
|
||||||
r = process_keyagent_request(request, response, con);
|
r = process_keyagent_request(request, response, con);
|
||||||
@ -132,8 +189,6 @@ process_request(struct agent_connection* con) {
|
|||||||
r = process_pubkeyagent_request(request, response, con);
|
r = process_pubkeyagent_request(request, response, con);
|
||||||
else if (con->type == PUBKEY_AUTH_AGENT)
|
else if (con->type == PUBKEY_AUTH_AGENT)
|
||||||
r = process_authagent_request(request, response, con);
|
r = process_authagent_request(request, response, con);
|
||||||
else
|
|
||||||
r = EINVAL;
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (request)
|
if (request)
|
||||||
|
@ -40,9 +40,12 @@ static int
|
|||||||
get_user_root(struct agent_connection* con, HKEY *root){
|
get_user_root(struct agent_connection* con, HKEY *root){
|
||||||
int r = 0;
|
int r = 0;
|
||||||
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
|
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
|
||||||
return ERROR_INTERNAL_ERROR;
|
return -1;
|
||||||
|
|
||||||
r = RegOpenCurrentUser(KEY_ALL_ACCESS, root);
|
if (con->client_type > OTHER)
|
||||||
|
*root = HKEY_LOCAL_MACHINE;
|
||||||
|
else if (RegOpenCurrentUser(KEY_ALL_ACCESS, root) != ERROR_SUCCESS)
|
||||||
|
r = -1;
|
||||||
|
|
||||||
RevertToSelf();
|
RevertToSelf();
|
||||||
return r;
|
return r;
|
||||||
@ -52,8 +55,10 @@ static int
|
|||||||
convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **eblob, DWORD *eblen, int encrypt) {
|
convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **eblob, DWORD *eblen, int encrypt) {
|
||||||
int success = 0;
|
int success = 0;
|
||||||
DATA_BLOB in, out;
|
DATA_BLOB in, out;
|
||||||
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
|
|
||||||
return -1;
|
if (con->client_type == OTHER)
|
||||||
|
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
in.cbData = blen;
|
in.cbData = blen;
|
||||||
in.pbData = (char*)blob;
|
in.pbData = (char*)blob;
|
||||||
@ -61,12 +66,16 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
|
|||||||
out.pbData = NULL;
|
out.pbData = NULL;
|
||||||
|
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
if (!CryptProtectData(&in, NULL, NULL, 0, NULL, 0, &out))
|
if (!CryptProtectData(&in, NULL, NULL, 0, NULL, 0, &out)) {
|
||||||
|
debug("cannot encrypt data");
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!CryptUnprotectData(&in, NULL, NULL, 0, NULL, 0, &out))
|
if (!CryptUnprotectData(&in, NULL, NULL, 0, NULL, 0, &out)) {
|
||||||
|
debug("cannot decrypt data");
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*eblob = malloc(out.cbData);
|
*eblob = malloc(out.cbData);
|
||||||
@ -79,7 +88,8 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
|
|||||||
done:
|
done:
|
||||||
if (out.pbData)
|
if (out.pbData)
|
||||||
LocalFree(out.pbData);
|
LocalFree(out.pbData);
|
||||||
RevertToSelf();
|
if (con->client_type == OTHER)
|
||||||
|
RevertToSelf();
|
||||||
return success? 0: -1;
|
return success? 0: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,9 +192,11 @@ static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
|
|||||||
(tmpbuf = sshbuf_from(keyblob, keyblob_len)) == NULL)
|
(tmpbuf = sshbuf_from(keyblob, keyblob_len)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if ( sshkey_private_deserialize(tmpbuf, &prikey) != 0 ||
|
if (sshkey_private_deserialize(tmpbuf, &prikey) != 0 ||
|
||||||
sshkey_sign(prikey, sig, siglen, blob, blen, 0) != 0)
|
sshkey_sign(prikey, sig, siglen, blob, blen, 0) != 0) {
|
||||||
|
debug("cannot sign using retrieved key");
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
success = 1;
|
success = 1;
|
||||||
|
|
||||||
@ -221,6 +233,7 @@ process_sign_request(struct sshbuf* request, struct sshbuf* response, struct age
|
|||||||
sshbuf_get_string_direct(request, &data, &dlen) != 0 ||
|
sshbuf_get_string_direct(request, &data, &dlen) != 0 ||
|
||||||
sshbuf_get_u32(request, &flags) != 0 ||
|
sshbuf_get_u32(request, &flags) != 0 ||
|
||||||
sshkey_from_blob(blob, blen, &key) != 0) {
|
sshkey_from_blob(blob, blen, &key) != 0) {
|
||||||
|
debug("sign request is invalid");
|
||||||
request_invalid = 1;
|
request_invalid = 1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -403,6 +416,8 @@ int process_keyagent_request(struct sshbuf* request, struct sshbuf* response, st
|
|||||||
|
|
||||||
if ((r = sshbuf_get_u8(request, &type)) != 0)
|
if ((r = sshbuf_get_u8(request, &type)) != 0)
|
||||||
return r;
|
return r;
|
||||||
|
debug2("process key agent request type %d", type);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SSH2_AGENTC_ADD_IDENTITY:
|
case SSH2_AGENTC_ADD_IDENTITY:
|
||||||
return process_add_identity(request, response, con);
|
return process_add_identity(request, response, con);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user