This commit is contained in:
manojampalam 2016-05-03 19:58:18 -07:00
parent abea0182ac
commit 1627b8c145
7 changed files with 87 additions and 64 deletions

View File

@ -95,7 +95,7 @@ ssh_get_authentication_socket(int *fdp)
*fdp = -1;
#ifdef WIN32_FIXME
#define SSH_AGENT_ROOT "SYSTEM\\CurrentControlSet\\Control\\SSH\\agent"
#define SSH_AGENT_ROOT "SOFTWARE\\SSH\\Agent"
HKEY agent_root = 0;
DWORD agent_pid = 0, tmp_size = 4, pipe_server_pid = 0xff;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, SSH_AGENT_ROOT, 0, KEY_QUERY_VALUE, &agent_root);

View File

@ -35,14 +35,27 @@
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
static int
get_user_root(struct agent_connection* con, HKEY *root){
int r = 0;
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
return ERROR_INTERNAL_ERROR;
r = RegOpenCurrentUser(KEY_ALL_ACCESS, root);
RevertToSelf();
return r;
}
int
process_add_identity(struct sshbuf* request, struct sshbuf* response, HANDLE client) {
process_add_identity(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
struct sshkey* key = NULL;
int r = 0, r1 = 0, blob_len;
size_t comment_len, pubkey_blob_len;
u_char *pubkey_blob = NULL;
char *thumbprint = NULL, *blob, *comment;
HKEY reg = 0, sub = 0;
char *thumbprint = NULL, *comment;
const char *blob;
HKEY reg = 0, sub = 0, user_root = 0;
blob = sshbuf_ptr(request);
if ((r = sshkey_private_deserialize(request, &key)) != 0)
@ -53,39 +66,29 @@ process_add_identity(struct sshbuf* request, struct sshbuf* response, HANDLE cli
goto done;
}
if ((r = sshbuf_peek_string_direct(request, &comment, &comment_len)) != 0)
goto done;
if ((thumbprint = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL)
goto done;
if ((r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SSHD_HOST_KEYS_ROOT,
0, KEY_WRITE, &reg)) != 0)
goto done;
if ((r = RegCreateKeyExA(reg, thumbprint, 0, 0, 0, KEY_WRITE, NULL, &sub, NULL)) != 0)
goto done;
if ((r = RegSetValueEx(sub, NULL, 0, REG_BINARY, blob, blob_len)) != 0)
goto done;
if ((r = RegSetValueEx(sub, L"pub", 0, REG_BINARY, pubkey_blob, pubkey_blob_len)) != 0)
goto done;
if ((r = RegSetValueEx(sub, L"type", 0, REG_DWORD, &key->type, 4)) != 0)
goto done;
if ((r = RegSetValueEx(sub, L"comment", 0, REG_BINARY, comment, comment_len)) != 0)
if (((r = sshbuf_peek_string_direct(request, &comment, &comment_len)) != 0) ||
((thumbprint = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) ||
((r = get_user_root(con, &user_root)) != 0) ||
((r = RegCreateKeyExW(user_root, SSHD_KEYS_ROOT, 0, 0, 0, KEY_WRITE, NULL, &reg, NULL)) != 0) ||
((r = RegCreateKeyExA(reg, thumbprint, 0, 0, 0, KEY_WRITE, NULL, &sub, NULL)) != 0) ||
((r = RegSetValueExW(sub, NULL, 0, REG_BINARY, blob, blob_len)) != 0) ||
((r = RegSetValueExW(sub, L"pub", 0, REG_BINARY, pubkey_blob, pubkey_blob_len)) != 0) ||
((r = RegSetValueExW(sub, L"type", 0, REG_DWORD, (BYTE*)&key->type, 4)) != 0) ||
((r = RegSetValueExW(sub, L"comment", 0, REG_BINARY, comment, comment_len)) != 0) )
goto done;
done:
/* TODO if r failed the delete reg entries*/
r1 = sshbuf_put_u8(response, (r==0) ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
if (key)
sshkey_free(key);
if (thumbprint)
free(thumbprint);
if (user_root)
RegCloseKey(user_root);
if (reg)
RegCloseKey(reg);
if (sub)
@ -96,8 +99,8 @@ done:
}
static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
const u_char *blob, size_t blen, u_int flags) {
HKEY reg = 0, sub = 0;
const u_char *blob, size_t blen, u_int flags, struct agent_connection* con) {
HKEY reg = 0, sub = 0, user_root = 0;
int r = 0;
struct sshkey* prikey = NULL;
char *thumbprint = NULL, *regdata = NULL;
@ -113,15 +116,18 @@ static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
if ((thumbprint = sshkey_fingerprint(pubkey, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL)
goto done;
if ((r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SSHD_HOST_KEYS_ROOT,
if ((r = get_user_root(con, &user_root)) != 0)
goto done;
if ((r = RegOpenKeyExW(user_root, SSHD_KEYS_ROOT,
0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &reg)) != 0)
goto done;
if ((r = RegOpenKeyEx(reg, thumbprint, 0, 0, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
NULL, &sub, NULL)) != 0)
if ((r = RegOpenKeyExA(reg, thumbprint, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
&sub)) != 0)
goto done;
if ((RegQueryValueEx(sub, NULL, 0, NULL, regdata, &regdatalen)) != ERROR_MORE_DATA) {
if ((RegQueryValueExW(sub, NULL, 0, NULL, regdata, &regdatalen)) != ERROR_MORE_DATA) {
r = EOTHER;
goto done;
}
@ -131,7 +137,7 @@ static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
goto done;
}
if ((r = RegQueryValueEx(sub, NULL, 0, NULL, regdata, &regdatalen)) != 0)
if ((r = RegQueryValueExW(sub, NULL, 0, NULL, regdata, &regdatalen)) != 0)
goto done;
if ((tmpbuf = sshbuf_from(regdata, regdatalen)) == NULL) {
@ -152,6 +158,8 @@ done:
sshkey_free(prikey);
if (thumbprint)
free(thumbprint);
if (user_root)
RegCloseKey(user_root);
if (reg)
RegCloseKey(reg);
if (sub)
@ -161,7 +169,7 @@ done:
}
int
process_sign_request(struct sshbuf* request, struct sshbuf* response, HANDLE client) {
process_sign_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
u_char *blob, *data, *signature = NULL;
size_t blen, dlen, slen = 0;
u_int flags = 0;
@ -177,7 +185,7 @@ process_sign_request(struct sshbuf* request, struct sshbuf* response, HANDLE cli
if (((r = sshkey_from_blob(blob, blen, &key)) != 0)
|| ((r = sign_blob(key, &signature, &slen,
data, dlen, 0)) != 0))
data, dlen, 0, con)) != 0))
goto done;
done:
@ -196,24 +204,29 @@ done:
}
int
process_request_identities(struct sshbuf* request, struct sshbuf* response, HANDLE client) {
process_request_identities(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
int r, r1, count = 0, index = 0;
HKEY root = NULL, sub = NULL;
HKEY root = NULL, sub = NULL, user_root = 0;
char* count_ptr = NULL;
wchar_t sub_name[MAX_KEY_LENGTH];
DWORD sub_name_len = MAX_KEY_LENGTH;
char *regdata = NULL;
DWORD regdatalen = 0, key_count = 0;
struct sshbuf* identities;
regdata = malloc(4);
regdatalen = 4;
if ((r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SSHD_HOST_KEYS_ROOT,
0, STANDARD_RIGHTS_READ | KEY_ENUMERATE_SUB_KEYS, &root)) != 0)
identities = sshbuf_new();
if ((identities == NULL) || (regdata == NULL))
goto done;
if (((r = sshbuf_put_u8(response, SSH2_AGENT_IDENTITIES_ANSWER)) != 0)
|| ((r = sshbuf_reserve(response, 4, &count_ptr)) != 0))
if ((r = get_user_root(con, &user_root)) != 0)
goto done;
if ((r = RegOpenKeyExW(user_root, SSHD_KEYS_ROOT,
0, STANDARD_RIGHTS_READ | KEY_ENUMERATE_SUB_KEYS, &root)) != 0)
goto done;
while (1) {
@ -222,9 +235,9 @@ process_request_identities(struct sshbuf* request, struct sshbuf* response, HAND
RegCloseKey(sub);
sub = NULL;
}
if ((r = RegEnumKeyEx(root, index++, sub_name, &sub_name_len, NULL, NULL, NULL, NULL)) == 0) {
if ((r = RegOpenKeyEx(root, sub_name, 0, KEY_QUERY_VALUE, &sub)) == 0) {
if ((r = RegQueryValueEx(sub, L"pub", 0, NULL, regdata, &regdatalen)) != 0) {
if ((r = RegEnumKeyExW(root, index++, sub_name, &sub_name_len, NULL, NULL, NULL, NULL)) == 0) {
if ((r = RegOpenKeyExW(root, sub_name, 0, KEY_QUERY_VALUE, &sub)) == 0) {
if ((r = RegQueryValueExW(sub, L"pub", 0, NULL, regdata, &regdatalen)) != 0) {
if (r == ERROR_MORE_DATA) {
r = 0;
if (regdata)
@ -233,7 +246,7 @@ process_request_identities(struct sshbuf* request, struct sshbuf* response, HAND
r = ENOMEM;
goto done;
}
if ((r = RegQueryValueEx(sub, L"pub", 0, NULL, regdata, &regdatalen)) != 0)
if ((r = RegQueryValueExW(sub, L"pub", 0, NULL, regdata, &regdatalen)) != 0)
goto done;
}
@ -243,10 +256,10 @@ process_request_identities(struct sshbuf* request, struct sshbuf* response, HAND
}
}
if ((r = sshbuf_put_string(response, regdata, regdatalen)) != 0)
if ((r = sshbuf_put_string(identities, regdata, regdatalen)) != 0)
goto done;
if ((r = RegQueryValueEx(sub, L"comment", 0, NULL, regdata, &regdatalen)) != 0) {
if ((r = RegQueryValueExW(sub, L"comment", 0, NULL, regdata, &regdatalen)) != 0) {
if (r == ERROR_MORE_DATA) {
r = 0;
if (regdata)
@ -255,7 +268,7 @@ process_request_identities(struct sshbuf* request, struct sshbuf* response, HAND
r = ENOMEM;
goto done;
}
if ((r = RegQueryValueEx(sub, L"comment", 0, NULL, regdata, &regdatalen)) != 0)
if ((r = RegQueryValueExW(sub, L"comment", 0, NULL, regdata, &regdatalen)) != 0)
goto done;
}
@ -264,7 +277,7 @@ process_request_identities(struct sshbuf* request, struct sshbuf* response, HAND
goto done;
}
}
if ((r = sshbuf_put_string(response, regdata, regdatalen)) != 0)
if ((r = sshbuf_put_string(identities, regdata, regdatalen)) != 0)
goto done;
key_count++;
@ -285,11 +298,19 @@ process_request_identities(struct sshbuf* request, struct sshbuf* response, HAND
}
POKE_U32(count_ptr, key_count);
if (((r = sshbuf_put_u8(response, SSH2_AGENT_IDENTITIES_ANSWER)) != 0)
|| ((r = sshbuf_put_u32(response, key_count)) != 0)
|| ((r = sshbuf_putb(response, identities)) != 0))
goto done;
done:
if (regdata)
free(regdata);
if (identities)
sshbuf_free(identities);
if (user_root)
RegCloseKey(user_root);
if (root)
RegCloseKey(root);
if (sub)

View File

@ -11,4 +11,6 @@ typedef unsigned __int64 u_int64_t;
#include "digest.h"
int process_add_identity(struct sshbuf*, struct sshbuf*, HANDLE);
int process_add_identity(struct sshbuf*, struct sshbuf*, struct agent_connection*);
int process_request_identities(struct sshbuf*, struct sshbuf*, struct agent_connection*);
int process_sign_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);

View File

@ -65,7 +65,7 @@ void agent_sm_process_action_queue() {
memset(&sa, 0, sizeof(sa));
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = NULL;
h = CreateNamedPipe(
h = CreateNamedPipeW(
AGENT_PIPE_ID, // pipe name
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_BYTE | // message type pipe
@ -165,9 +165,8 @@ int agent_start() {
QueueUserWorkItem(iocp_work, NULL, 0);
agent_listen();
RegOpenKeyEx(HKEY_LOCAL_MACHINE, SSH_AGENT_ROOT,
0, KEY_SET_VALUE, &agent_root);
RegSetValueEx(agent_root, L"ProcessID", 0, REG_DWORD, &process_id, 4);
RegCreateKeyExW(HKEY_LOCAL_MACHINE, SSH_AGENT_ROOT, 0, 0, 0, KEY_WRITE, 0, &agent_root, 0);
RegSetValueExW(agent_root, L"ProcessID", 0, REG_DWORD, (BYTE*)&process_id, 4);
iocp_work(NULL);
return 1;
}

View File

@ -2,15 +2,14 @@
#include <stdio.h>
#define MAX_MESSAGE_SIZE 5 * 1024
#define SSH_ROOT L"SYSTEM\\CurrentControlSet\\Control\\SSH"
#define SSH_AGENT_ROOT SSH_ROOT L"\\agent"
#define SSHD_HOST_KEYS_ROOT SSH_ROOT L"\\Host\\Keys"
#define SSH_ROOT L"SOFTWARE\\SSH"
#define SSH_AGENT_ROOT SSH_ROOT L"\\Agent"
#define SSHD_KEYS_ROOT SSH_ROOT L"\\Keys"
#define HEADER_SIZE 4
struct agent_connection {
OVERLAPPED ol;
HANDLE connection;
HANDLE client_token;
struct {
DWORD num_bytes;
DWORD transferred;

View File

@ -133,13 +133,13 @@ process_request(struct agent_connection* con) {
switch (type) {
case SSH2_AGENTC_ADD_IDENTITY:
r = process_add_identity(request, response, con->client_token);
r = process_add_identity(request, response, con);
break;
case SSH2_AGENTC_REQUEST_IDENTITIES:
r = process_request_identities(request, response, con->client_token);
r = process_request_identities(request, response, con);
break;
case SSH2_AGENTC_SIGN_REQUEST:
r = process_sign_request(request, response, con->client_token);
r = process_sign_request(request, response, con);
break;
default:
r = EINVAL;

4
sshd.c
View File

@ -2242,7 +2242,9 @@ main(int ac, char **av)
error("Could not connect to agent \"%s\": %s",
options.host_key_agent, ssh_err(r));
}
#ifdef WIN32_FIXME
have_agent = 1;
#endif
for (i = 0; i < options.num_host_key_files; i++) {
if (options.host_key_files[i] == NULL)
continue;