1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-06 22:12:47 -05:00

Make Pageant use the same SID-selection logic as the Pageant client

code (as introduced in r9043), so that it uses the user SID rather
than the default SID.

This does change the access-control model, in that a Pageant running
with administrator privilege will now serve keys to an unprivileged
PuTTY running as the same user who started Pageant. Owen and I think
this isn't a problem (in particular, it will still not serve keys to a
_different_ user).

More importantly, making the Pageant client and server code work the
same way means that PuTTY and Pageant can still talk to each other
when UAC is turned off, which we've had several reports of r9043
having broken.

[originally from svn r9178]
[r9043 == 05f22632eb]
This commit is contained in:
Simon Tatham
2011-06-08 20:47:07 +00:00
parent 6e40a0db57
commit af78191a9c
3 changed files with 96 additions and 54 deletions

View File

@ -86,15 +86,70 @@ DECL_WINDOWS_FUNCTION(static, BOOL, InitializeSecurityDescriptor,
(PSECURITY_DESCRIPTOR, DWORD));
DECL_WINDOWS_FUNCTION(static, BOOL, SetSecurityDescriptorOwner,
(PSECURITY_DESCRIPTOR, PSID, BOOL));
static int init_advapi(void)
DECL_WINDOWS_FUNCTION(, DWORD, GetSecurityInfo,
(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
PSID *, PSID *, PACL *, PACL *,
PSECURITY_DESCRIPTOR *));
int init_advapi(void)
{
advapi = load_system32_dll("advapi32.dll");
return advapi &&
GET_WINDOWS_FUNCTION(advapi, GetSecurityInfo) &&
GET_WINDOWS_FUNCTION(advapi, OpenProcessToken) &&
GET_WINDOWS_FUNCTION(advapi, GetTokenInformation) &&
GET_WINDOWS_FUNCTION(advapi, InitializeSecurityDescriptor) &&
GET_WINDOWS_FUNCTION(advapi, SetSecurityDescriptorOwner);
}
PSID get_user_sid(void)
{
HANDLE proc = NULL, tok = NULL;
TOKEN_USER *user = NULL;
DWORD toklen, sidlen;
PSID sid = NULL, ret = NULL;
if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
GetCurrentProcessId())) == NULL)
goto cleanup;
if (!p_OpenProcessToken(proc, TOKEN_QUERY, &tok))
goto cleanup;
if (!p_GetTokenInformation(tok, TokenUser, NULL, 0, &toklen) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto cleanup;
if ((user = (TOKEN_USER *)LocalAlloc(LPTR, toklen)) == NULL)
goto cleanup;
if (!p_GetTokenInformation(tok, TokenUser, user, toklen, &toklen))
goto cleanup;
sidlen = GetLengthSid(user->User.Sid);
sid = (PSID)smalloc(sidlen);
if (!CopySid(sidlen, sid, user->User.Sid))
goto cleanup;
/* Success. Move sid into the return value slot, and null it out
* to stop the cleanup code freeing it. */
ret = sid;
sid = NULL;
cleanup:
if (proc != NULL)
CloseHandle(proc);
if (tok != NULL)
CloseHandle(tok);
if (user != NULL)
LocalFree(user);
if (sid != NULL)
sfree(sid);
return ret;
}
#endif
int agent_query(void *in, int inlen, void **out, int *outlen,
@ -108,8 +163,7 @@ int agent_query(void *in, int inlen, void **out, int *outlen,
COPYDATASTRUCT cds;
SECURITY_ATTRIBUTES sa, *psa;
PSECURITY_DESCRIPTOR psd = NULL;
HANDLE proc, tok;
TOKEN_USER *user = NULL;
PSID usersid = NULL;
*out = NULL;
*outlen = 0;
@ -130,31 +184,16 @@ int agent_query(void *in, int inlen, void **out, int *outlen,
* run PSFTPs which refer back to the owning user's
* unprivileged Pageant.
*/
if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
GetCurrentProcessId())) != NULL) {
if (p_OpenProcessToken(proc, TOKEN_QUERY, &tok)) {
DWORD retlen;
p_GetTokenInformation(tok, TokenUser, NULL, 0, &retlen);
user = (TOKEN_USER *)LocalAlloc(LPTR, retlen);
if (!p_GetTokenInformation(tok, TokenUser,
user, retlen, &retlen)) {
LocalFree(user);
user = NULL;
}
CloseHandle(tok);
}
CloseHandle(proc);
}
usersid = get_user_sid();
psa = NULL;
if (user) {
if (usersid) {
psd = (PSECURITY_DESCRIPTOR)
LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (psd) {
if (p_InitializeSecurityDescriptor
(psd, SECURITY_DESCRIPTOR_REVISION) &&
p_SetSecurityDescriptorOwner(psd, user->User.Sid, FALSE)) {
p_SetSecurityDescriptorOwner(psd, usersid, FALSE)) {
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = psd;
@ -221,7 +260,6 @@ int agent_query(void *in, int inlen, void **out, int *outlen,
CloseHandle(filemap);
if (psd)
LocalFree(psd);
if (user)
LocalFree(user);
sfree(usersid);
return 1;
}