From d70f60ae52b946d174468a4dff49702daa93dc9a Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 19 Sep 2000 16:29:28 +0000 Subject: [PATCH] Improved means of IPC between agent and PuTTY git-svn-id: svn://svn.tartarus.org/sgt/putty@601 cda61777-01e9-0310-a592-d414129be87e --- pageant.c | 173 ++++++++++++++++++++++++++++++++++--------------------------- pageantc.c | 136 +++++++++++------------------------------------- 2 files changed, 126 insertions(+), 183 deletions(-) diff --git a/pageant.c b/pageant.c index 66392753..7133c8d5 100644 --- a/pageant.c +++ b/pageant.c @@ -3,6 +3,7 @@ */ #include +#include #include /* FIXME */ #include "putty.h" /* FIXME */ #include "ssh.h" @@ -14,7 +15,13 @@ #define WM_XUSER (WM_USER + 0x2000) #define WM_SYSTRAY (WM_XUSER + 6) #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_VIEWKEYS 0x0020 @@ -151,26 +158,17 @@ void add_keyfile(char *filename) { /* * This is the main agent function that answers messages. */ -void answer_msg(void *in, int inlen, void **out, int *outlen) { - unsigned char *ret; - unsigned char *p = in; +void answer_msg(void *msg) { + unsigned char *p = msg; + unsigned char *ret = msg; 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. */ type = p[4]; p += 5; - switch (type) { 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. */ len += 5 + 4; - if ((ret = malloc(len)) != NULL) { - PUT_32BIT(ret, len-4); - ret[4] = SSH_AGENT_RSA_IDENTITIES_ANSWER; - PUT_32BIT(ret+5, nkeys); - p = ret + 5 + 4; - for (key = first234(rsakeys, &e); key; key = next234(&e)) { - PUT_32BIT(p, ssh1_bignum_bitcount(key->modulus)); - p += 4; - p += ssh1_write_bignum(p, key->exponent); - p += ssh1_write_bignum(p, key->modulus); - PUT_32BIT(p, strlen(key->comment)); - memcpy(p+4, key->comment, strlen(key->comment)); - p += 4 + strlen(key->comment); - } + if (len > AGENT_MAX_MSGLEN) + goto failure; /* aaargh! too much stuff! */ + PUT_32BIT(ret, len-4); + ret[4] = SSH_AGENT_RSA_IDENTITIES_ANSWER; + PUT_32BIT(ret+5, nkeys); + p = ret + 5 + 4; + for (key = first234(rsakeys, &e); key; key = next234(&e)) { + PUT_32BIT(p, ssh1_bignum_bitcount(key->modulus)); + p += 4; + p += ssh1_write_bignum(p, key->exponent); + p += ssh1_write_bignum(p, key->modulus); + PUT_32BIT(p, strlen(key->comment)); + memcpy(p+4, key->comment, strlen(key->comment)); + p += 4 + strlen(key->comment); } } break; @@ -258,11 +256,9 @@ void answer_msg(void *in, int inlen, void **out, int *outlen) { * bytes of MD5. */ len = 5 + 16; - if ((ret = malloc(len)) != NULL) { - PUT_32BIT(ret, len-4); - ret[4] = SSH_AGENT_RSA_RESPONSE; - memcpy(ret+5, response_md5, 16); - } + PUT_32BIT(ret, len-4); + ret[4] = SSH_AGENT_RSA_RESPONSE; + memcpy(ret+5, response_md5, 16); } break; #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. */ - if ((ret = malloc(5)) != NULL) { - PUT_32BIT(ret, 1); - ret[4] = SSH_AGENT_FAILURE; - } + PUT_32BIT(ret, 1); + ret[4] = SSH_AGENT_FAILURE; 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: { COPYDATASTRUCT *cds; - void *in, *out, *ret; - int inlen, outlen; - HANDLE filemap; - char mapname[64]; - int id; + char *mapname; + void *p; + HANDLE filemap, proc; + PSID mapowner, procowner; + PSECURITY_DESCRIPTOR psd1 = NULL, psd2 = NULL; + int ret = 0; cds = (COPYDATASTRUCT *)lParam; - /* - * FIXME: use dwData somehow. - */ - in = cds->lpData; - inlen = cds->cbData; - answer_msg(in, inlen, &out, &outlen); - if (out) { - id = 0; - do { - sprintf(mapname, "PageantReply%08x", ++id); - filemap = CreateFileMapping(INVALID_HANDLE_VALUE, - NULL, PAGE_READWRITE, - 0, outlen+sizeof(int), - mapname); - } while (filemap == INVALID_HANDLE_VALUE); - ret = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, - outlen+sizeof(int)); - if (ret) { - *((int *)ret) = outlen; - memcpy(((int *)ret)+1, out, outlen); - UnmapViewOfFile(ret); - return id; + if (cds->dwData != AGENT_COPYDATA_ID) + return 0; /* not our message, mate */ + mapname = (char *)cds->lpData; + if (mapname[cds->cbData - 1] != '\0') + return 0; /* failure to be ASCIZ! */ +#ifdef DEBUG_IPC + debug(("mapname is :%s:\r\n", mapname)); +#endif + filemap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, mapname); +#ifdef DEBUG_IPC + debug(("filemap is %p\r\n", filemap)); +#endif + if (filemap != NULL && filemap != INVALID_HANDLE_VALUE) { + int rc; + if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE, + GetCurrentProcessId())) == NULL) { +#ifdef DEBUG_IPC + debug(("couldn't get handle for process\r\n")); +#endif + return 0; + } + if (GetSecurityInfo(proc, SE_KERNEL_OBJECT, + 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; } - } else - return 0; /* invalid request */ +#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); diff --git a/pageantc.c b/pageantc.c index e718313e..49b588eb 100644 --- a/pageantc.c +++ b/pageantc.c @@ -6,12 +6,21 @@ #include #include +#define AGENT_COPYDATA_ID 0x804e50ba /* random goop */ +#define AGENT_MAX_MSGLEN 8192 + #ifdef TESTMODE #define debug(x) (printf x) #else #define debug(x) #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) { HWND hwnd; hwnd = FindWindow("Pageant", "Pageant"); @@ -22,93 +31,10 @@ int agent_exists(void) { } 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; char mapname[64]; HANDLE filemap; - void *p, *ret; + unsigned char *p, *ret; int id, retlen; COPYDATASTRUCT cds; @@ -119,34 +45,30 @@ void agent_query(void *in, int inlen, void **out, int *outlen) { debug(("hwnd is %p\n", hwnd)); if (!hwnd) return; - cds.dwData = 0; /* FIXME */ - cds.cbData = inlen; - cds.lpData = in; + sprintf(mapname, "PageantRequest%08x", GetCurrentThreadId()); + filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, + 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); debug(("return is %d\n", id)); if (id > 0) { - sprintf(mapname, "PageantReply%08x", id); - filemap = OpenFileMapping(FILE_MAP_READ, FALSE, mapname); - debug(("name is `%s', filemap is %p\n", mapname, filemap)); - debug(("error is %d\n", GetLastError())); - if (filemap != NULL && filemap != INVALID_HANDLE_VALUE) { - p = MapViewOfFile(filemap, FILE_MAP_READ, 0, 0, 0); - debug(("p is %p\n", p)); - 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); + retlen = 4 + GET_32BIT(p); + debug(("len is %d\n", retlen)); + ret = malloc(retlen); + if (ret) { + memcpy(ret, p, retlen); + *out = ret; + *outlen = retlen; } - /* FIXME: tell agent to close its handle too */ } + UnmapViewOfFile(p); + CloseHandle(filemap); } #ifdef TESTMODE -- 2.11.0