1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-02-03 21:52:24 +00:00

Improved means of IPC between agent and PuTTY

[originally from svn r601]
This commit is contained in:
Simon Tatham 2000-09-19 16:29:28 +00:00
parent 9119c6e02f
commit 0e67e1b291
2 changed files with 126 additions and 183 deletions

173
pageant.c
View File

@ -3,6 +3,7 @@
*/ */
#include <windows.h> #include <windows.h>
#include <aclapi.h>
#include <stdio.h> /* FIXME */ #include <stdio.h> /* FIXME */
#include "putty.h" /* FIXME */ #include "putty.h" /* FIXME */
#include "ssh.h" #include "ssh.h"
@ -14,7 +15,13 @@
#define WM_XUSER (WM_USER + 0x2000) #define WM_XUSER (WM_USER + 0x2000)
#define WM_SYSTRAY (WM_XUSER + 6) #define WM_SYSTRAY (WM_XUSER + 6)
#define WM_SYSTRAY2 (WM_XUSER + 7) #define WM_SYSTRAY2 (WM_XUSER + 7)
#define WM_CLOSEMEM (WM_XUSER + 10)
#define AGENT_COPYDATA_ID 0x804e50ba /* random goop */
/*
* FIXME: maybe some day we can sort this out ...
*/
#define AGENT_MAX_MSGLEN 8192
#define IDM_CLOSE 0x0010 #define IDM_CLOSE 0x0010
#define IDM_VIEWKEYS 0x0020 #define IDM_VIEWKEYS 0x0020
@ -151,26 +158,17 @@ void add_keyfile(char *filename) {
/* /*
* This is the main agent function that answers messages. * This is the main agent function that answers messages.
*/ */
void answer_msg(void *in, int inlen, void **out, int *outlen) { void answer_msg(void *msg) {
unsigned char *ret; unsigned char *p = msg;
unsigned char *p = in; unsigned char *ret = msg;
int type; int type;
*out = NULL; /* default `no go' response */
/*
* Basic sanity checks. len >= 5, and len[0:4] holds len-4.
*/
if (inlen < 5 || GET_32BIT(p) != (unsigned long)(inlen-4))
return;
/* /*
* Get the message type. * Get the message type.
*/ */
type = p[4]; type = p[4];
p += 5; p += 5;
switch (type) { switch (type) {
case SSH_AGENTC_REQUEST_RSA_IDENTITIES: case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
/* /*
@ -198,20 +196,20 @@ void answer_msg(void *in, int inlen, void **out, int *outlen) {
* bytes for the key count. * bytes for the key count.
*/ */
len += 5 + 4; len += 5 + 4;
if ((ret = malloc(len)) != NULL) { if (len > AGENT_MAX_MSGLEN)
PUT_32BIT(ret, len-4); goto failure; /* aaargh! too much stuff! */
ret[4] = SSH_AGENT_RSA_IDENTITIES_ANSWER; PUT_32BIT(ret, len-4);
PUT_32BIT(ret+5, nkeys); ret[4] = SSH_AGENT_RSA_IDENTITIES_ANSWER;
p = ret + 5 + 4; PUT_32BIT(ret+5, nkeys);
for (key = first234(rsakeys, &e); key; key = next234(&e)) { p = ret + 5 + 4;
PUT_32BIT(p, ssh1_bignum_bitcount(key->modulus)); for (key = first234(rsakeys, &e); key; key = next234(&e)) {
p += 4; PUT_32BIT(p, ssh1_bignum_bitcount(key->modulus));
p += ssh1_write_bignum(p, key->exponent); p += 4;
p += ssh1_write_bignum(p, key->modulus); p += ssh1_write_bignum(p, key->exponent);
PUT_32BIT(p, strlen(key->comment)); p += ssh1_write_bignum(p, key->modulus);
memcpy(p+4, key->comment, strlen(key->comment)); PUT_32BIT(p, strlen(key->comment));
p += 4 + strlen(key->comment); memcpy(p+4, key->comment, strlen(key->comment));
} p += 4 + strlen(key->comment);
} }
} }
break; break;
@ -258,11 +256,9 @@ void answer_msg(void *in, int inlen, void **out, int *outlen) {
* bytes of MD5. * bytes of MD5.
*/ */
len = 5 + 16; len = 5 + 16;
if ((ret = malloc(len)) != NULL) { PUT_32BIT(ret, len-4);
PUT_32BIT(ret, len-4); ret[4] = SSH_AGENT_RSA_RESPONSE;
ret[4] = SSH_AGENT_RSA_RESPONSE; memcpy(ret+5, response_md5, 16);
memcpy(ret+5, response_md5, 16);
}
} }
break; break;
#if 0 /* FIXME: implement these */ #if 0 /* FIXME: implement these */
@ -285,17 +281,10 @@ void answer_msg(void *in, int inlen, void **out, int *outlen) {
/* /*
* Unrecognised message. Return SSH_AGENT_FAILURE. * Unrecognised message. Return SSH_AGENT_FAILURE.
*/ */
if ((ret = malloc(5)) != NULL) { PUT_32BIT(ret, 1);
PUT_32BIT(ret, 1); ret[4] = SSH_AGENT_FAILURE;
ret[4] = SSH_AGENT_FAILURE;
}
break; break;
} }
if (ret) {
*out = ret;
*outlen = 4 + GET_32BIT(ret);
}
} }
/* /*
@ -465,45 +454,77 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
case WM_COPYDATA: case WM_COPYDATA:
{ {
COPYDATASTRUCT *cds; COPYDATASTRUCT *cds;
void *in, *out, *ret; char *mapname;
int inlen, outlen; void *p;
HANDLE filemap; HANDLE filemap, proc;
char mapname[64]; PSID mapowner, procowner;
int id; PSECURITY_DESCRIPTOR psd1 = NULL, psd2 = NULL;
int ret = 0;
cds = (COPYDATASTRUCT *)lParam; cds = (COPYDATASTRUCT *)lParam;
/* if (cds->dwData != AGENT_COPYDATA_ID)
* FIXME: use dwData somehow. return 0; /* not our message, mate */
*/ mapname = (char *)cds->lpData;
in = cds->lpData; if (mapname[cds->cbData - 1] != '\0')
inlen = cds->cbData; return 0; /* failure to be ASCIZ! */
answer_msg(in, inlen, &out, &outlen); #ifdef DEBUG_IPC
if (out) { debug(("mapname is :%s:\r\n", mapname));
id = 0; #endif
do { filemap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, mapname);
sprintf(mapname, "PageantReply%08x", ++id); #ifdef DEBUG_IPC
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, debug(("filemap is %p\r\n", filemap));
NULL, PAGE_READWRITE, #endif
0, outlen+sizeof(int), if (filemap != NULL && filemap != INVALID_HANDLE_VALUE) {
mapname); int rc;
} while (filemap == INVALID_HANDLE_VALUE); if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
ret = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, GetCurrentProcessId())) == NULL) {
outlen+sizeof(int)); #ifdef DEBUG_IPC
if (ret) { debug(("couldn't get handle for process\r\n"));
*((int *)ret) = outlen; #endif
memcpy(((int *)ret)+1, out, outlen); return 0;
UnmapViewOfFile(ret);
return id;
} }
} else if (GetSecurityInfo(proc, SE_KERNEL_OBJECT,
return 0; /* invalid request */ OWNER_SECURITY_INFORMATION,
&procowner, NULL, NULL, NULL,
&psd2) != ERROR_SUCCESS) {
#ifdef DEBUG_IPC
debug(("couldn't get owner info for process\r\n"));
#endif
CloseHandle(proc);
return 0; /* unable to get security info */
}
CloseHandle(proc);
if ((rc = GetSecurityInfo(filemap, SE_KERNEL_OBJECT,
OWNER_SECURITY_INFORMATION,
&mapowner, NULL, NULL, NULL,
&psd1) != ERROR_SUCCESS)) {
#ifdef DEBUG_IPC
debug(("couldn't get owner info for filemap: %d\r\n", rc));
#endif
return 0;
}
#ifdef DEBUG_IPC
debug(("got security stuff\r\n"));
#endif
if (!EqualSid(mapowner, procowner))
return 0; /* security ID mismatch! */
#ifdef DEBUG_IPC
debug(("security stuff matched\r\n"));
#endif
LocalFree(psd1);
LocalFree(psd2);
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
#ifdef DEBUG_IPC
debug(("p is %p\r\n", p));
{int i; for(i=0;i<5;i++)debug(("p[%d]=%02x\r\n", i, ((unsigned char *)p)[i]));}
#endif
answer_msg(p);
ret = 1;
UnmapViewOfFile(p);
}
CloseHandle(filemap);
return ret;
} }
break;
case WM_CLOSEMEM:
/*
* FIXME!
*/
break;
} }
return DefWindowProc (hwnd, message, wParam, lParam); return DefWindowProc (hwnd, message, wParam, lParam);

View File

@ -6,12 +6,21 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define AGENT_COPYDATA_ID 0x804e50ba /* random goop */
#define AGENT_MAX_MSGLEN 8192
#ifdef TESTMODE #ifdef TESTMODE
#define debug(x) (printf x) #define debug(x) (printf x)
#else #else
#define debug(x) #define debug(x)
#endif #endif
#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) { int agent_exists(void) {
HWND hwnd; HWND hwnd;
hwnd = FindWindow("Pageant", "Pageant"); hwnd = FindWindow("Pageant", "Pageant");
@ -22,93 +31,10 @@ int agent_exists(void) {
} }
void agent_query(void *in, int inlen, void **out, int *outlen) { void agent_query(void *in, int inlen, void **out, int *outlen) {
#if 0
#define MAILSLOTNAME "\\\\.\\mailslot\\pageant_listener"
SECURITY_ATTRIBUTES sa;
HANDLE my_mailslot, agent_mailslot;
char name[64];
char *p;
DWORD msglen, byteswritten, bytesread, inid;
*out = NULL;
*outlen = 0;
agent_mailslot = CreateFile(MAILSLOTNAME, GENERIC_WRITE,
FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL);
debug(("opened %s: %p\n", MAILSLOTNAME, agent_mailslot));
if (agent_mailslot == INVALID_HANDLE_VALUE)
return;
inid = GetCurrentThreadId();
inid--;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
do {
sprintf(name, "\\\\.\\mailslot\\pclient_request_%08x", ++inid);
/*
* Five-minute timeout.
*/
my_mailslot = CreateMailslot(name, 0, 0, &sa);
debug(("mailslot %s: %p\n", name, my_mailslot));
} while (my_mailslot == INVALID_HANDLE_VALUE);
Sleep(3000);
msglen = strlen(name) + 1 + inlen;
p = malloc(msglen);
if (!p) {
CloseHandle(my_mailslot);
CloseHandle(agent_mailslot);
return;
}
strcpy(p, name);
memcpy(p+strlen(p)+1, in, inlen);
debug(("ooh\n"));
if (WriteFile(agent_mailslot, p, msglen, &byteswritten, NULL) == 0) {
debug(("eek!\n"));
free(p);
CloseHandle(my_mailslot);
CloseHandle(agent_mailslot);
return;
}
debug(("aah\n"));
free(p);
CloseHandle(agent_mailslot);
WaitForSingleObject(my_mailslot, 3000000);
debug(("waited\n"));
if (!GetMailslotInfo(my_mailslot, NULL, &msglen, NULL, NULL)) {
CloseHandle(my_mailslot);
return;
}
if (msglen == MAILSLOT_NO_MESSAGE) {
debug(("no message\n"));
CloseHandle(my_mailslot);
return;
}
debug(("msglen=%d\n", msglen));
p = malloc(msglen);
if (!p) {
CloseHandle(my_mailslot);
return;
}
if (ReadFile(my_mailslot, p, msglen, &bytesread, NULL) == 0 &&
bytesread == msglen) {
*out = p;
*outlen = msglen;
}
CloseHandle(my_mailslot);
#endif
HWND hwnd; HWND hwnd;
char mapname[64]; char mapname[64];
HANDLE filemap; HANDLE filemap;
void *p, *ret; unsigned char *p, *ret;
int id, retlen; int id, retlen;
COPYDATASTRUCT cds; COPYDATASTRUCT cds;
@ -119,34 +45,30 @@ void agent_query(void *in, int inlen, void **out, int *outlen) {
debug(("hwnd is %p\n", hwnd)); debug(("hwnd is %p\n", hwnd));
if (!hwnd) if (!hwnd)
return; return;
cds.dwData = 0; /* FIXME */ sprintf(mapname, "PageantRequest%08x", GetCurrentThreadId());
cds.cbData = inlen; filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
cds.lpData = in; 0, AGENT_MAX_MSGLEN, mapname);
if (!filemap)
return;
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
memcpy(p, in, inlen);
cds.dwData = AGENT_COPYDATA_ID;
cds.cbData = 1+strlen(mapname);
cds.lpData = mapname;
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds); id = SendMessage(hwnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
debug(("return is %d\n", id)); debug(("return is %d\n", id));
if (id > 0) { if (id > 0) {
sprintf(mapname, "PageantReply%08x", id); retlen = 4 + GET_32BIT(p);
filemap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname); debug(("len is %d\n", retlen));
debug(("name is `%s', filemap is %p\n", mapname, filemap)); ret = malloc(retlen);
debug(("error is %d\n", GetLastError())); if (ret) {
if (filemap != NULL && filemap != INVALID_HANDLE_VALUE) { memcpy(ret, p, retlen);
p = MapViewOfFile(filemap, FILE_MAP_READ, 0, 0, 0); *out = ret;
debug(("p is %p\n", p)); *outlen = retlen;
if (p) {
retlen = *(int *)p;
debug(("len is %d\n", retlen));
ret = malloc(retlen);
if (ret) {
memcpy(ret, ((int *)p) + 1, retlen);
*out = ret;
*outlen = retlen;
}
UnmapViewOfFile(p);
}
CloseHandle(filemap);
} }
/* FIXME: tell agent to close its handle too */
} }
UnmapViewOfFile(p);
CloseHandle(filemap);
} }
#ifdef TESTMODE #ifdef TESTMODE