Skip to content

Commit 61554ba

Browse files
committed
5-3 c4
1 parent 42e4efa commit 61554ba

File tree

1 file changed

+71
-7
lines changed

1 file changed

+71
-7
lines changed

contrib/win32/win32compat/ssh-agent/agent-request.c

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include "agent.h"
3333
#include "agent-request.h"
34+
#include <sddl.h>
3435

3536
#define MAX_KEY_LENGTH 255
3637
#define MAX_VALUE_NAME 16383
@@ -47,31 +48,84 @@ get_user_root(struct agent_connection* con, HKEY *root){
4748
return r;
4849
}
4950

51+
static int
52+
convert_blob(struct agent_connection* con, char *blob, DWORD blen, char **eblob, DWORD *eblen, int encrypt) {
53+
int r = 0;
54+
DATA_BLOB in, out;
55+
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
56+
return ERROR_INTERNAL_ERROR;
57+
58+
in.cbData = blen;
59+
in.pbData = blob;
60+
out.cbData = 0;
61+
out.pbData = NULL;
62+
63+
if (encrypt) {
64+
if (!CryptProtectData(&in, NULL, NULL, 0, NULL, 0, &out)) {
65+
r = GetLastError();
66+
goto done;
67+
}
68+
}
69+
else {
70+
if (!CryptUnprotectData(&in, NULL, NULL, 0, NULL, 0, &out)) {
71+
r = GetLastError();
72+
goto done;
73+
}
74+
}
75+
76+
77+
78+
79+
*eblob = malloc(out.cbData);
80+
if (*eblob == NULL) {
81+
r = ERROR_OUTOFMEMORY;
82+
goto done;
83+
}
84+
85+
memcpy(*eblob, out.pbData, out.cbData);
86+
*eblen = out.cbData;
87+
done:
88+
if (out.cbData)
89+
LocalFree(out.cbData);
90+
RevertToSelf();
91+
return r;
92+
}
93+
5094
int
5195
process_add_identity(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
5296
struct sshkey* key = NULL;
53-
int r = 0, r1 = 0, blob_len;
97+
int r = 0, r1 = 0, blob_len, eblob_len;
5498
size_t comment_len, pubkey_blob_len;
5599
u_char *pubkey_blob = NULL;
56100
char *thumbprint = NULL, *comment;
57101
const char *blob;
102+
char* eblob = NULL;
58103
HKEY reg = 0, sub = 0, user_root = 0;
104+
PSECURITY_DESCRIPTOR sd = NULL;
105+
wchar_t* str = L"O:SYG:BAD:P(A;;GA;;;SY)";
106+
SECURITY_ATTRIBUTES sa;
107+
ConvertStringSecurityDescriptorToSecurityDescriptorW(str, SDDL_REVISION_1, &sd, NULL);
108+
sa.nLength = sizeof(sa);
109+
sa.lpSecurityDescriptor = sd;
110+
sa.bInheritHandle = FALSE;
59111

60112
blob = sshbuf_ptr(request);
61113
if ((r = sshkey_private_deserialize(request, &key)) != 0)
62114
goto done;
63115
blob_len = (sshbuf_ptr(request) - blob) & 0xffffffff;
64116

65-
if ((r = sshkey_to_blob(key, &pubkey_blob, &pubkey_blob_len)) != 0) {
117+
if ((r = sshkey_to_blob(key, &pubkey_blob, &pubkey_blob_len)) != 0)
118+
goto done;
119+
120+
if ((r = convert_blob(con, blob, blob_len, &eblob, &eblob_len, 1)) != 0)
66121
goto done;
67-
}
68122

69123
if (((r = sshbuf_peek_string_direct(request, &comment, &comment_len)) != 0) ||
70124
((thumbprint = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) ||
71125
((r = get_user_root(con, &user_root)) != 0) ||
72126
((r = RegCreateKeyExW(user_root, SSHD_KEYS_ROOT, 0, 0, 0, KEY_WRITE, NULL, &reg, NULL)) != 0) ||
73127
((r = RegCreateKeyExA(reg, thumbprint, 0, 0, 0, KEY_WRITE, NULL, &sub, NULL)) != 0) ||
74-
((r = RegSetValueExW(sub, NULL, 0, REG_BINARY, blob, blob_len)) != 0) ||
128+
((r = RegSetValueExW(sub, NULL, 0, REG_BINARY, eblob, eblob_len)) != 0) ||
75129
((r = RegSetValueExW(sub, L"pub", 0, REG_BINARY, pubkey_blob, pubkey_blob_len)) != 0) ||
76130
((r = RegSetValueExW(sub, L"type", 0, REG_DWORD, (BYTE*)&key->type, 4)) != 0) ||
77131
((r = RegSetValueExW(sub, L"comment", 0, REG_BINARY, comment, comment_len)) != 0) )
@@ -83,6 +137,10 @@ process_add_identity(struct sshbuf* request, struct sshbuf* response, struct age
83137

84138
r1 = sshbuf_put_u8(response, (r==0) ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
85139

140+
if (eblob)
141+
free(eblob);
142+
if (sd)
143+
LocalFree(sd);
86144
if (key)
87145
sshkey_free(key);
88146
if (thumbprint)
@@ -104,8 +162,9 @@ static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
104162
int r = 0;
105163
struct sshkey* prikey = NULL;
106164
char *thumbprint = NULL, *regdata = NULL;
107-
DWORD regdatalen = 0;
108-
struct sshbuf* tmpbuf;
165+
DWORD regdatalen = 0, keyblob_len = 0;;
166+
struct sshbuf* tmpbuf = NULL;
167+
char *keyblob = NULL;
109168

110169
regdata = malloc(4);
111170
regdatalen = 4;
@@ -140,7 +199,10 @@ static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
140199
if ((r = RegQueryValueExW(sub, NULL, 0, NULL, regdata, &regdatalen)) != 0)
141200
goto done;
142201

143-
if ((tmpbuf = sshbuf_from(regdata, regdatalen)) == NULL) {
202+
if ((r = convert_blob(con, regdata, regdatalen, &keyblob, &keyblob_len, FALSE)) != 0)
203+
goto done;
204+
205+
if ((tmpbuf = sshbuf_from(keyblob, keyblob_len)) == NULL) {
144206
r = ENOMEM;
145207
goto done;
146208
}
@@ -150,6 +212,8 @@ static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
150212
goto done;
151213

152214
done:
215+
if (keyblob)
216+
free(keyblob);
153217
if (regdata)
154218
free(regdata);
155219
if (tmpbuf)

0 commit comments

Comments
 (0)