Skip to content

Commit b108327

Browse files
committed
Added unicode support in ssh-agent auth requests
1 parent 3266df9 commit b108327

File tree

5 files changed

+61
-42
lines changed

5 files changed

+61
-42
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ agent_listen_loop() {
212212
void agent_cleanup_connection(struct agent_connection* con) {
213213
debug("connection %p clean up", con);
214214
CloseHandle(con->connection);
215+
if (con->hProfile)
216+
UnloadUserProfile(con->auth_token, con->hProfile);
217+
if (con->auth_token)
218+
CloseHandle(con->auth_token);
215219
free(con);
216220
CloseHandle(ioc_port);
217221
ioc_port = NULL;

contrib/win32/win32compat/ssh-agent/agent.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ struct agent_connection {
3131
LOCAL_SYSTEM,
3232
SSHD,
3333
NETWORK_SERVICE
34-
} client_type;
34+
} client_process;
35+
HANDLE auth_token;
36+
HANDLE hProfile;
3537
};
3638

3739
void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);

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

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ EnablePrivilege(const char *privName, int enabled)
7979

8080

8181
void
82-
LoadProfile(HANDLE token, char* user, char* domain) {
83-
PROFILEINFOA profileInfo;
82+
LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
83+
PROFILEINFOW profileInfo;
8484
profileInfo.dwFlags = PI_NOUI;
8585
profileInfo.lpProfilePath = NULL;
8686
profileInfo.lpUserName = user;
@@ -91,11 +91,12 @@ LoadProfile(HANDLE token, char* user, char* domain) {
9191
profileInfo.dwSize = sizeof(profileInfo);
9292
EnablePrivilege("SeBackupPrivilege", 1);
9393
EnablePrivilege("SeRestorePrivilege", 1);
94-
if (LoadUserProfileA(token, &profileInfo) == FALSE)
95-
debug("Loading user profile failed ERROR: %d", GetLastError());
94+
if (LoadUserProfileW(con->auth_token, &profileInfo) == FALSE)
95+
debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError());
96+
else
97+
con->hProfile = profileInfo.hProfile;
9698
EnablePrivilege("SeBackupPrivilege", 0);
9799
EnablePrivilege("SeRestorePrivilege", 0);
98-
99100
}
100101

101102
#define MAX_USER_LEN 256
@@ -200,7 +201,7 @@ generate_user_token(wchar_t* user) {
200201
&token,
201202
&quotas,
202203
&subStatus) != STATUS_SUCCESS) {
203-
debug("LsaRegisterLogonProcess failed");
204+
debug("LsaLogonUser failed");
204205
goto done;
205206
}
206207

@@ -218,10 +219,12 @@ generate_user_token(wchar_t* user) {
218219
#define PUBKEY_AUTH_REQUEST "pubkey"
219220
#define PASSWD_AUTH_REQUEST "password"
220221
#define MAX_USER_NAME_LEN 256
222+
#define MAX_PW_LEN 128
221223

222224
int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
223-
char *user = NULL, *pwd = NULL, *dom = NULL, *tmp;
224-
//wchar_t *userW = NULL, *domW = NULL, *pwdW = NULL;
225+
char *user = NULL, *pwd = NULL;
226+
wchar_t userW_buf[MAX_USER_NAME_LEN], pwdW_buf[MAX_PW_LEN];
227+
wchar_t *userW = userW_buf, *domW = NULL, *pwdW = pwdW_buf, *tmp;
225228
size_t user_len = 0, pwd_len = 0, dom_len = 0;
226229
int r = -1;
227230
HANDLE token = 0, dup_token, client_proc = 0;
@@ -235,20 +238,25 @@ int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response
235238
goto done;
236239
}
237240

238-
/*TODO - support Unicode*/
241+
userW[0] = L'\0';
242+
if (MultiByteToWideChar(CP_UTF8, 0, user, user_len + 1, userW, MAX_USER_NAME_LEN) == 0 ||
243+
MultiByteToWideChar(CP_UTF8, 0, pwd, pwd_len + 1, pwdW, MAX_PW_LEN) == 0) {
244+
debug("unable to convert user (%s) or password to UTF-16", user);
245+
goto done;
246+
}
239247

240-
if ((tmp = strchr(user, '\\')) != NULL) {
241-
dom = user;
242-
user = tmp + 1;
243-
*tmp = '\0';
248+
if ((tmp = wcschr(userW, L'\\')) != NULL) {
249+
domW = userW;
250+
userW = tmp + 1;
251+
*tmp = L'\0';
244252

245253
}
246-
else if ((tmp = strchr(user, '@')) != NULL) {
247-
dom = tmp + 1;
248-
*tmp = '\0';
254+
else if ((tmp = wcschr(userW, L'@')) != NULL) {
255+
domW = tmp + 1;
256+
*tmp = L'\0';
249257
}
250258

251-
if (LogonUser(user, dom, pwd, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token) == FALSE ||
259+
if (LogonUserW(userW, domW, pwdW, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token) == FALSE ||
252260
(FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) ||
253261
((client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
254262
(FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
@@ -257,7 +265,8 @@ int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response
257265
goto done;
258266
}
259267

260-
LoadProfile(token, user, dom);
268+
con->auth_token = token;
269+
LoadProfile(con, userW, domW);
261270
r = 0;
262271
done:
263272
/* TODO Fix this hacky protocol*/
@@ -268,8 +277,6 @@ int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response
268277
free(user);
269278
if (pwd)
270279
free(pwd);
271-
if (token)
272-
CloseHandle(token);
273280
if (client_proc)
274281
CloseHandle(client_proc);
275282

@@ -296,12 +303,15 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
296303
goto done;
297304
}
298305

306+
wuser[0] = L'\0';
299307
if (MultiByteToWideChar(CP_UTF8, 0, user, user_len + 1, wuser, MAX_USER_NAME_LEN) == 0 ||
300308
(token = generate_user_token(wuser)) == 0) {
301309
debug("unable to generate token for user %ls", wuser);
302310
goto done;
303311
}
304312

313+
con->auth_token = token;
314+
305315
if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, token, &wuser_home) != S_OK ||
306316
pubkey_allowed(key, wuser, wuser_home) != 1) {
307317
debug("given public key is not mapped to user %ls (profile:%ls)", wuser, wuser_home);
@@ -320,30 +330,33 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
320330
debug("failed to authorize user");
321331
goto done;
322332
}
323-
{
324-
/*TODO - support Unicode*/
325-
char *tmp, *u = user, *d = NULL;
326-
if ((tmp = strchr(user, '\\')) != NULL) {
327-
d = user;
328-
u = tmp + 1;
329-
*tmp = '\0';
330-
331-
}
332-
else if ((tmp = strchr(user, '@')) != NULL) {
333-
d = tmp + 1;
334-
*tmp = '\0';
335-
}
336-
LoadProfile(token, u, d);
333+
334+
{
335+
wchar_t *tmp, *userW, *domW;
336+
userW = wuser;
337+
if ((tmp = wcschr(userW, L'\\')) != NULL) {
338+
domW = userW;
339+
userW = tmp + 1;
340+
*tmp = L'\0';
341+
342+
}
343+
else if ((tmp = wcschr(userW, L'@')) != NULL) {
344+
domW = tmp + 1;
345+
*tmp = L'\0';
346+
}
347+
LoadProfile(con, userW, domW);
337348
}
338349

339350
r = 0;
340351
done:
352+
/* TODO Fix this hacky protocol*/
353+
if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
354+
r = 0;
355+
341356
if (user)
342357
free(user);
343358
if (key)
344359
sshkey_free(key);
345-
if (token)
346-
CloseHandle(token);
347360
if (wuser_home)
348361
CoTaskMemFree(wuser_home);
349362
if (client_proc)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ process_request(struct agent_connection* con) {
174174
int r = -1;
175175
struct sshbuf *request = NULL, *response = NULL;
176176

177-
if (con->client_type == UNKNOWN)
178-
if ((con->client_type = get_con_client_type(con->connection)) == -1)
177+
if (con->client_process == UNKNOWN)
178+
if ((con->client_process = get_con_client_type(con->connection)) == -1)
179179
goto done;
180180

181181

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ get_user_root(struct agent_connection* con, HKEY *root){
4343
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
4444
return -1;
4545

46-
if (con->client_type > OTHER)
46+
if (con->client_process > OTHER)
4747
*root = HKEY_LOCAL_MACHINE;
4848
else if (RegOpenCurrentUser(KEY_ALL_ACCESS, root) != ERROR_SUCCESS)
4949
r = -1;
@@ -59,7 +59,7 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
5959
int success = 0;
6060
DATA_BLOB in, out;
6161

62-
if (con->client_type == OTHER)
62+
if (con->client_process == OTHER)
6363
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
6464
return -1;
6565

@@ -91,7 +91,7 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
9191
done:
9292
if (out.pbData)
9393
LocalFree(out.pbData);
94-
if (con->client_type == OTHER)
94+
if (con->client_process == OTHER)
9595
RevertToSelf();
9696
return success? 0: -1;
9797
}

0 commit comments

Comments
 (0)