#include "putty.h"
+#ifndef NO_SECURITY
+#include "winsecur.h"
+#endif
+
#define AGENT_COPYDATA_ID 0x804e50ba /* random goop */
#define AGENT_MAX_MSGLEN 8192
-#define GET_32BIT(cp) \
- (((unsigned long)(unsigned char)(cp)[0] << 24) | \
- ((unsigned long)(unsigned char)(cp)[1] << 16) | \
- ((unsigned long)(unsigned char)(cp)[2] << 8) | \
- ((unsigned long)(unsigned char)(cp)[3]))
-
int agent_exists(void)
{
HWND hwnd;
unsigned char *p, *ret;
int id, retlen;
COPYDATASTRUCT cds;
+ SECURITY_ATTRIBUTES sa, *psa;
+ PSECURITY_DESCRIPTOR psd = NULL;
+ PSID usersid = NULL;
*out = NULL;
*outlen = 0;
if (!hwnd)
return 1; /* *out == NULL, so failure */
mapname = dupprintf("PageantRequest%08x", (unsigned)GetCurrentThreadId());
- filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+
+ psa = NULL;
+#ifndef NO_SECURITY
+ if (got_advapi()) {
+ /*
+ * Make the file mapping we create for communication with
+ * Pageant owned by the user SID rather than the default. This
+ * should make communication between processes with slightly
+ * different contexts more reliable: in particular, command
+ * prompts launched as administrator should still be able to
+ * run PSFTPs which refer back to the owning user's
+ * unprivileged Pageant.
+ */
+ usersid = get_user_sid();
+
+ if (usersid) {
+ psd = (PSECURITY_DESCRIPTOR)
+ LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
+ if (psd) {
+ if (p_InitializeSecurityDescriptor
+ (psd, SECURITY_DESCRIPTOR_REVISION) &&
+ p_SetSecurityDescriptorOwner(psd, usersid, FALSE)) {
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = psd;
+ psa = &sa;
+ } else {
+ LocalFree(psd);
+ psd = NULL;
+ }
+ }
+ }
+ }
+#endif /* NO_SECURITY */
+
+ filemap = CreateFileMapping(INVALID_HANDLE_VALUE, psa, PAGE_READWRITE,
0, AGENT_MAX_MSGLEN, mapname);
- if (!filemap)
+ if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
+ sfree(mapname);
return 1; /* *out == NULL, so failure */
+ }
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
memcpy(p, in, inlen);
cds.dwData = AGENT_COPYDATA_ID;
data->hwnd = hwnd;
if (CreateThread(NULL, 0, agent_query_thread, data, 0, &threadid))
return 0;
+ sfree(mapname);
sfree(data);
}
#endif
}
UnmapViewOfFile(p);
CloseHandle(filemap);
+ sfree(mapname);
+ if (psd)
+ LocalFree(psd);
return 1;
}